How to manage resolutions with libGdx on Android 2.2? - java

I tried everything I could, but my libgdx application won't scale down on android 2.2. It displays a full image of 640x480 on a screen of only 480x320. Here's the code I got so far;
private static final int VIRTUAL_WIDTH = 640;
private static final int VIRTUAL_HEIGHT = 480;
private static final float ASPECT_RATIO = (float)VIRTUAL_WIDTH/(float)VIRTUAL_HEIGHT;
public static Texture BMP_BACKGROUND;
public static Rectangle viewport;
public static OrthographicCamera camera;
public static SpriteBatch batch;
public void create()
{
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
BMP_BACKGROUND = new Texture(Gdx.files.internal("data/bmpSpaceBackground.png"));
BMP_BACKGROUND.setFilter(TextureFilter.Nearest, TextureFilter.Nearest);
batch = new SpriteBatch();
camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
}
#Override
public void dispose()
{
batch.dispose();
BMP_BACKGROUND.dispose();
}
#Override
public void render()
{
camera.update();
camera.apply(Gdx.gl10);
// set viewport
Gdx.gl.glViewport((int) viewport.x, (int) viewport.y,
(int) viewport.width, (int) viewport.height);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.draw(BMP_BACKGROUND, 0, 0);
Game.run();
}
public void resize(int width, int height)
{
float aspectRatio = (float)width/(float)height;
float scale = 1f;
Vector2 crop = new Vector2(0f, 0f);
if(aspectRatio > ASPECT_RATIO)
{
scale = (float)height/(float)VIRTUAL_HEIGHT;
crop.x = (width - VIRTUAL_WIDTH*scale)/2f;
}
else if(aspectRatio < ASPECT_RATIO)
{
scale = (float)width/(float)VIRTUAL_WIDTH;
crop.y = (height - VIRTUAL_HEIGHT*scale)/2f;
}
else
{
scale = (float)width/(float)VIRTUAL_WIDTH;
}
float w = (float)VIRTUAL_WIDTH*scale;
float h = (float)VIRTUAL_HEIGHT*scale;
viewport = new Rectangle((int)crop.x, (int)crop.y, (int)w, (int)h);
}
Anyone can tell me what I'm doing wrong?

Try this
public void resize(int width, int height)
{
cam.viewportHeight = height; //set the viewport
cam.viewportWidth = width;
if (Config.VIRTUAL_VIEW_WIDTH / cam.viewportWidth < Config.VIRTUAL_VIEW_HEIGHT
/ cam.viewportHeight) {
//sett the right zoom direct
cam.zoom = Config.VIRTUAL_VIEW_HEIGHT / cam.viewportHeight;
} else {
//sett the right zoom direct
cam.zoom = Config.VIRTUAL_VIEW_WIDTH / cam.viewportWidth;
}
cam.update();
}
This does work and i can work with the virutal resolution. But dont forget to set the camera of your stage you are using! Else it does have no effect!
stage.setCamera(camera).
if you have done that you can work with the virtual resolution inside of your stage.
regards
Your code is 1:1 from an example online.

Related

Libgdx updating animation

I'm learning libgdx and currently doing a flappy bird demo. For fun I tried to implement when the score reached a certain number the bird sprite texture will update and change to another color. Instead of using the spritebatch and changing the color through tinting I wanted to create a new texture(png file).
The problem is since it is a sprite it needs to be animated so the wings will flap. When I try and update the texture at runtime it will only work but the animation wont play.
Here is my bird class:
public class Bird {
private static final int GRAVITY = -15;
private static final int MOVEMENT = 100;
private Vector3 position;
private Vector3 velocity;
private Rectangle bounds;
private Animation birdAnimation;
private Texture birdTexture;
private TextureRegion textureRegion;
private Sound flap;
public Bird(int x, int y){
position = new Vector3(x, y, 0);
velocity = new Vector3(0, 0, 0);
textureRegion = new TextureRegion(returnTexture());
birdAnimation = new Animation(textureRegion, 3, 0.5f);
bounds = new Rectangle(x, y, returnTexture().getWidth() / 3, returnTexture().getHeight());
flap = Gdx.audio.newSound(Gdx.files.internal("sfx_wing.ogg"));
}
public void update(float dt){
textureRegion = new TextureRegion(returnTexture());
birdAnimation = new Animation(textureRegion, 3, 0.5f);
birdAnimation.update(dt);
if(position.y > 0){
velocity.add(0, GRAVITY, 0);
}
velocity.scl(dt);
position.add(MOVEMENT * dt, velocity.y, 0);
if(position.y < 0){
position.y = 0;
}
velocity.scl(1/dt);
bounds.setPosition(position.x, position.y);
}
public TextureRegion getTexture() {
return birdAnimation.getFrame();
}
public Texture returnTexture(){
if(PlayState.score > 1){
return birdTexture = new Texture("birdanimation1.png");
}else{
return birdTexture = new Texture("birdanimation.png");
}
}
public Vector3 getPosition() {
return position;
}
public void jump(){
velocity.y = 250;
flap.play(0.15f);
}
public Rectangle getBounds(){
return bounds;
}
public void dispose(){
returnTexture().dispose();
flap.dispose();
}
}
Here is my animation class:
public class Animation {
private Array<TextureRegion> frames;
private float maxFrameTime;
private float currentFrameTime;
private int frameCount;
private int frame;
public Animation(TextureRegion region, int frameCount, float cycleTime){
frames = new Array<TextureRegion>();
int frameWidth = region.getRegionWidth() / frameCount;
for(int i = 0; i < frameCount; i++){
frames.add(new TextureRegion(region, i * frameWidth, 0, frameWidth, region.getRegionHeight()));
}
this.frameCount = frameCount;
maxFrameTime = cycleTime / frameCount;
frame = 0;
}
public void update(float dt){
currentFrameTime += dt;
if(currentFrameTime > maxFrameTime){
frame++;
currentFrameTime = 0;
}
if(frame >= frameCount){
frame = 0;
}
}
public TextureRegion getFrame(){
return frames.get(frame);
}
}
Here's my render code in my play state:
#Override
public void render(SpriteBatch sb) {
sb.setProjectionMatrix(cam.combined);
sb.begin();
sb.draw(bg, cam.position.x - (cam.viewportWidth /2), 0);
sb.draw(bird.getTexture(), bird.getPosition().x, bird.getPosition().y);
for(Tube tube : tubes){
sb.draw(tube.getTopTube(), tube.getPosTopTube().x, tube.getPosTopTube().y);
sb.draw(tube.getBottomTube(), tube.getPosBotTube().x, tube.getPosBotTube().y);
}
sb.draw(ground, groundPos1.x, groundPos1.y);
sb.draw(ground, groundPos2.x, groundPos2.y);
font.draw(sb, text, cam.position.x - gl.width / 2, cam.position.y + 200);
sb.end();
}
If you need any other classes just ask. I'm probably making a stupid mistake or just coding it entirely wrong for what I'm trying to achieve.
Thanks, Jackson
You need to NOT load your textures every single frame.
libgdx has its own Animation class so you don't need to make your own.
Here is an example on animation from libgdx's github:
2D Animation
To make it simple, just have 2 animaitons on Bird and switch between them when you need to.

Android : moving bmp leaving a trail ( Surface View and Canvas )

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.

Java libGDX will not draw sprites when the camera coordinates do not match the window coordinates

I am having a problem with the libGDX engine. I have a pair of variables to set the width and height of the screen, and another pair to set the width and height of the camera. However, whenever the camera is not the same size as the screen, the engine will not render any sprites. Here is my code for you to look at:
My Constants:
public abstract class Constants
{
public static final int WINDOW_WIDTH = 800;
public static final int WINDOW_HEIGHT = 600;
public static final int CAMERA_WIDTH = 800;
public static final int CAMERA_HEIGHT = 600;
}
Where the Sprite is Created:
public class GameController
{
public static final String TAG = GameController.class.getName();
public Sprite[] testSprites;
public int selectedSprite;
public GameController()
{
init();
}
private void init()
{
initTestObjects();
}
private void initTestObjects()
{
testSprites = new Sprite[1];
int width = 32;
int height = 32;
Pixmap pixmap = createProceduralPixmap(width, height);
Texture texture = new Texture(pixmap);
for(int i = 0; i < testSprites.length; i++)
{
Sprite spr = new Sprite(texture);
spr.setSize(32, 32);
spr.setOrigin(spr.getWidth() / 2.0f, spr.getHeight() / 2.0f);
spr.setPosition(0, 0);
testSprites[i] = spr;
}
selectedSprite = 0;
}
private Pixmap createProceduralPixmap(int width, int height)
{
Pixmap pixmap = new Pixmap(width, height, Format.RGBA8888);
pixmap.setColor(1, 0, 0, 0.5f);
pixmap.fill();
pixmap.setColor(1, 1, 0, 1);
pixmap.drawLine(0, 0, width, height);
pixmap.drawLine(width, 0, 0, height);
pixmap.setColor(0, 1, 1, 1);
pixmap.drawRectangle(0, 0, width, height);
return pixmap;
}
public void update(float deltaTime)
{
updateTestObjects(deltaTime);
}
public void updateTestObjects(float deltaTime)
{
float rotation = testSprites[selectedSprite].getRotation();
rotation += 90 * deltaTime;
rotation %= 360;
testSprites[selectedSprite].setRotation(rotation);
}
}
And the Drawing:
public class GameRenderer implements Disposable
{
public static final String TAG = GameRenderer.class.getName();
private OrthographicCamera camera;
private SpriteBatch batch;
private GameController gameController;
public GameRenderer(GameController gameController)
{
this.gameController = gameController;
init();
}
private void init()
{
batch = new SpriteBatch();
camera = new OrthographicCamera(Constants.CAMERA_WIDTH,
Constants.CAMERA_HEIGHT);
camera.position.set(0, 0, 0);
camera.update();
}
public void render()
{
renderTestObjects();
}
private void renderTestObjects()
{
batch.setProjectionMatrix(camera.combined);
batch.begin();
for(Sprite sprite : gameController.testSprites)
{
sprite.draw(batch);
}
batch.end();
}
public void resize(int width, int height)
{
camera.viewportWidth =
(Constants.CAMERA_HEIGHT / height) * width;
camera.update();
}
#Override
public void dispose()
{
batch.dispose();
}
}
The code above works fine and will render a sprite in the center of the screen, but when I change CAMERA_WIDTH and CAMERA_HEIGHT to say 80 and 60 respectively, instead of making the sprite 10x larger like it should, it doesn't draw anything. Any advice?
You are dividing ints by ints, so you end up with poorly scaled numbers. For example:
camera.viewportWidth =
(Constants.CAMERA_HEIGHT / height) * width;
If the screen width and height are 800 and 600, and CAMERA_HEIGHT is 60, then the equation becomes
camera.viewportWidth =
(60 / 600) * 800;
which becomes (due to pure integer math):
camera.viewportWidth =
(0) * 800;
which becomes 0. You need to cast those ints to floats before dividing! This may not be the only issue, but it alone could be causing your problem.

Black Screen and cleaning the code (LibGDX)

I'm following video tutorials using libGdx and kinda adapting the code to get what I want. I managed to draw the HUD and an animation, but when I tried to add a button following another tutorial I ended with a black screen, here is the code:
public class WorldRenderer implements ApplicationListener, Screen {
Pixmap pixmap;
SpriteBatch batch;
private Skin skin;
private Stage stage;
OrthographicCamera cam;
Table table;
TextButton buttonShake;
BitmapFont white;
BitmapFont black;
private TextureAtlas atlas;
Texture virusTexture;
Texture hudTexture;
private static final float HUD_WIDTH = 480f;
private static final float HUD_HEIGHT = 800f;
private static final float WALK_ANIM_WIDTH = 337f;
private static final float WALK_ANIM_HEIGHT = 213f;
public static final int SCREEN_WIDTH = 480;
public static final int SCREEN_HEIGHT = 800;
private static final int FRAME_COLS = 2;
private static final int FRAME_ROWS = 2;
Animation walkAnimation;
Texture walkSheet;
TextureRegion[] walkFrames;
TextureRegion currentFrame;
float stateTime;
float width, height;
Hud hud;
public WorldRenderer(World world) {
this.world = world;
walkSheet = new Texture("data/character.png");
TextureRegion[][] tmp = TextureRegion.split(walkSheet,
walkSheet.getWidth() / FRAME_COLS, walkSheet.getHeight()
/ FRAME_ROWS);
walkFrames = new TextureRegion[FRAME_COLS * FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++) {
for (int j = 0; j < FRAME_COLS; j++) {
walkFrames[index++] = tmp[i][j];
}
}
walkAnimation = new Animation(0.25f, walkFrames);
stateTime = 0f;
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
cam = new OrthographicCamera(SCREEN_WIDTH, SCREEN_HEIGHT);
cam.position.set(SCREEN_WIDTH / 2f, SCREEN_HEIGHT / 2f, 0);
batch = new SpriteBatch();
batch.setProjectionMatrix(cam.combined);
hudTexture = new Texture("data/hud.png");
hudTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
}
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
cam.update();
stage.act(delta);
stateTime += Gdx.graphics.getDeltaTime();
currentFrame = walkAnimation.getKeyFrame(stateTime, true);
hud = world.getHud();
batch.setProjectionMatrix(cam.combined);
batch.begin();
batch.draw(hudTexture, SCREEN_WIDTH / 2f - HUD_WIDTH / 2f,
SCREEN_HEIGHT / 2f - HUD_HEIGHT / 2f);
batch.draw(currentFrame, SCREEN_WIDTH / 2f - WALK_ANIM_WIDTH / 2f,
SCREEN_HEIGHT / 2f - WALK_ANIM_HEIGHT / 2f);
batch.end();
stage.draw();
}
public void dispose() {
batch.dispose();
virusTexture.dispose();
hudTexture.dispose();
skin.dispose();
atlas.dispose();
white.dispose();
black.dispose();
stage.dispose();
}
#Override
public void create() {
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void show() {
}
#Override
public void hide() {
// TODO Auto-generated method stub
}
#Override
public void render() {
// TODO Auto-generated method stub
}
I'm pretty sure you are also going to find unused lines of code so please point them out for me if you want so I can better organize my code and learn. Thanks!
One possible problem is that you implement an ApplicationListener and a Screen, both have the render method and almost the same methods.
You shouldn't implement both. If this is your app entry-point I would go for the applicationListener.
However, for the educational purpose you should read some topics about the Game class as your next app entry-point. Consider using separated "screens" that handle the render part and a "brain" that allows them to communicate with each other, this is where the Game class becomes handy.
Things can seem a little trickier at the beginning but will definitely make sense to you after a bit of studying ;)

libgdx why doesn't the Camera follow the character?

I'm new with libgdx and I have read a Tutorial (the Tutorial Code is my base).
I have a character that I can move, but the camera won't follow the character :(
Here's my WorldRenderer.java:
package com.evolutio.tee.view;
import com.evolutio.tee.model.Block;
import com.evolutio.tee.model.Tee;
import com.evolutio.tee.model.World;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.math.Rectangle;
public class WorldRenderer {
private static final float CAMERA_WIDTH = 10f;
private static final float CAMERA_HEIGHT = 7f;
private World world;
private OrthographicCamera cam;
/** for debug rendering **/
ShapeRenderer debugRenderer = new ShapeRenderer();
/** Textures **/
private Texture teeTexture;
private Texture blockTexture;
private SpriteBatch spriteBatch;
private boolean debug = false;
private int width;
private int height;
private float ppuX; // pixels per unit on the X axis
private float ppuY; // pixels per unit on the Y axis
public void setSize (int w, int h) {
this.width = w;
this.height = h;
ppuX = (float)width / CAMERA_WIDTH;
ppuY = (float)height / CAMERA_HEIGHT;
}
public WorldRenderer(World world, boolean debug) {
Tee tee = world.getTee();
this.world = world;
cam = new OrthographicCamera(CAMERA_WIDTH, CAMERA_HEIGHT);
cam.position.set(CAMERA_WIDTH / 2f, CAMERA_HEIGHT / 2f, 0);
cam.update();
this.debug = debug;
spriteBatch = new SpriteBatch();
loadTextures();
}
private void loadTextures() {
teeTexture = new Texture(Gdx.files.internal("tee/tee.png"));
blockTexture = new Texture(Gdx.files.internal("world/dreck.png"));
}
public void render() {
spriteBatch.begin();
drawBlocks();
drawTee();
spriteBatch.end();
//if (debug) drawDebug();
}
private void drawBlocks() {
for (Block block : world.getBlocks()) {
spriteBatch.draw(blockTexture, block.getPosition().x * ppuX, block.getPosition().y * ppuY, Block.SIZE * ppuX, Block.SIZE * ppuY);
}
}
private void drawTee() {
Tee tee = world.getTee();
spriteBatch.draw(teeTexture, tee.getPosition().x * ppuX, tee.getPosition().y * ppuY, Tee.SIZE * ppuX, Tee.SIZE * ppuY);
cam.position.set(tee.getPosition().x, tee.getPosition().y, 0);
}
private void drawDebug() {
// render blocks
debugRenderer.setProjectionMatrix(cam.combined);
debugRenderer.begin(ShapeType.Rectangle);
for (Block block : world.getBlocks()) {
Rectangle rect = block.getBounds();
float x1 = block.getPosition().x + rect.x;
float y1 = block.getPosition().y + rect.y;
debugRenderer.setColor(new Color(1, 0, 0, 1));
debugRenderer.rect(x1, y1, rect.width, rect.height);
}
// render Tee
Tee tee = world.getTee();
Rectangle rect = tee.getBounds();
float x1 = tee.getPosition().x + rect.x;
float y1 = tee.getPosition().y + rect.y;
debugRenderer.setColor(new Color(0, 1, 0, 1));
debugRenderer.rect(x1, y1, rect.width, rect.height);
debugRenderer.end();
}
}
at drawTee() I try to make the camera following the Tee.
cam.position.set(tee.getPosition().x, tee.getPosition().y, 0);
Try this
public class WorldRenderer {
private static final float CAMERA_WIDTH = 10f;
private static final float CAMERA_HEIGHT = 7f;
private World world;
private OrthographicCamera cam;
/** for debug rendering **/
ShapeRenderer debugRenderer = new ShapeRenderer();
/** Textures **/
private Texture teeTexture;
private Texture blockTexture;
private SpriteBatch spriteBatch;
private boolean debug = false;
private int width;
private int height;
private float ppuX; // pixels per unit on the X axis
private float ppuY; // pixels per unit on the Y axis
public void setSize (int w, int h) {
this.width = w;
this.height = h;
ppuX = (float)width / CAMERA_WIDTH;
ppuY = (float)height / CAMERA_HEIGHT;
}
public WorldRenderer(World world, boolean debug) {
Tee tee = world.getTee();
this.world = world;
this.cam = new OrthographicCamera(CAMERA_WIDTH, CAMERA_HEIGHT);
this.cam.setToOrtho(false,CAMERA_WIDTH,CAMERA_HEIGHT);
this.cam.position.set(CAMERA_WIDTH / 2f, CAMERA_HEIGHT / 2f, 0);
this.cam.update();
this.debug = debug;
spriteBatch = new SpriteBatch();
loadTextures();
}
private void loadTextures() {
teeTexture = new Texture(Gdx.files.internal("tee/tee.png"));
blockTexture = new Texture(Gdx.files.internal("world/dreck.png"));
}
public void render() {
moveCamera(tee.getPosition().x, CAMERA_HEIGHT / 2);
spriteBatch.setProjectionMatrix(cam.combined);
spriteBatch.begin();
drawBlocks();
drawTee();
spriteBatch.end();
//if (debug) drawDebug();
}
public void moveCamera(float x,float y){
if ((tee.getPosition().x > CAMERA_WIDTH / 2)) {
cam.position.set(x, y, 0);
cam.update();
}
}
private void drawBlocks() {
for (Block block : world.getBlocks()) {
spriteBatch.draw(blockTexture, block.getPosition().x, block.getPosition().y, Block.SIZE, Block.SIZE);
}
}
private void drawTee() {
Tee tee = world.getTee();
spriteBatch.draw(teeTexture, tee.getPosition().x, tee.getPosition().y, Tee.SIZE, Tee.SIZE);
}
Using the sprite.setProjectionMatrix(cam.combined) before the spriteBatch.begin() is needed because if you don't the spriteBatch uses it's own camera, therefore your updates do nothing for what appears on screen.
You have to take out the ppuX, ppuY stuff. I know that's to resize the screen for different devices, but it screws up the camera, therefore if you keep it in and call the setProjectionMatrix, it will be way way zoomed in (actually the size of all images will be huge.)

Categories

Resources