Java LibGDX sprite moving twice as fast as camera - java

So I've got a class which extends ApplicationAdapter implements InputProcessor and does the following when you drag around on the screen.
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
float x = Gdx.input.getDeltaX();
float y = Gdx.input.getDeltaY();
if (Store.isGameState) {
Store.Entity.player.setxMove(x);
Store.Entity.player.setyMove(-y);
}
return true;
}
In my player class I have a update method which does the following:
#Override
public void update() {
x += xMove;
y += yMove;
Store.Camera.Camera.position.set(Store.Entity.player.getXPos() + Store.Entity.player.getWidth() / 2, Store.Entity.player.getYPos() + Store.Entity.player.getHeight() / 2, 0);
Store.Camera.Camera.update();
}
and a render method which is:
public void render(SpriteBatch SB) {
SB.begin();
Store.Entity.sprite.setPosition(Store.Entity.player.getXPos(), Store.Entity.player.getYPos());
Store.Entity.sprite.draw(SB);
SB.end();
}
Which all-in-all works, the camera will move around as will my sprite. However my sprite does not move at the same speed as my camera and I can't for the life of me figure out why this is the case. The sprite moves roughly twice as fast as the camera does, and isn't centered on the player which I'd like ideally.
EDIT:
So in my GameState I have the following:
package com.imjoshscott.dataria.states;
import com.imjoshscott.dataria.Game;
import com.imjoshscott.dataria.Store;
public class GameState extends State {
public GameState(Game game) {
super(game);
Store.isGameState = true;
Store.Entity.getPlayer(game, Store.Entity.getSprite());
Store.Graphics.getSpriteBatch();
Store.Graphics.getTiledMap();
Store.Graphics.getTiledMapRenderer();
Store.Camera.getCamera();
Store.Camera.getHudCamera();
Store.Camera.Camera.setToOrtho(false, Game.GAME_WIDTH, Game.GAME_HEIGHT);
Store.Camera.HudCamera.setToOrtho(false, Game.GAME_WIDTH, Game.GAME_HEIGHT);
Store.Camera.Camera.viewportHeight = Game.GAME_HEIGHT / 2.5f;
Store.Camera.Camera.viewportWidth = Game.GAME_WIDTH / 2.5f;
}
#Override
public void update() {
Store.Graphics.tiledMapRenderer.setView(Store.Camera.Camera);
Store.Entity.player.update();
}
#Override
public void render() {
Store.Graphics.tiledMapRenderer.render();
Store.Entity.player.render(Store.Graphics.SB);
}
}
The Camera stuff in the Store class:
public static class Camera {
public static OrthographicCamera Camera;
public static OrthographicCamera HudCamera;
public static OrthographicCamera getCamera() {
if(Camera == null)
Camera = new OrthographicCamera();
return Camera;
}
public static OrthographicCamera getHudCamera() {
if(HudCamera == null)
HudCamera = new OrthographicCamera();
return HudCamera;
}
}
EDIT: Showing update & render methods
public void update() {
moveCreature();
Store.Entity.sprite.setPosition(Store.Entity.player.getXPos(), Store.Entity.player.getYPos());
Store.Camera.Camera.position.set(Store.Entity.player.getXPos(), Store.Entity.player.getYPos(), 0);
Store.Camera.Camera.update();
xMove = 0f;
yMove = 0f;
}
public void render(SpriteBatch SB) {
SB.begin();
Store.Entity.sprite.draw(SB);
SB.end();
}

Updated My previous answer is not correct, upon seeing and checking the project I saw this render() method for GameState class (after looked around for several places but no dice, if ever found this very weird problem again I would direct to this).
public void render() {
Store.Graphics.tiledMapRenderer.render();
Store.Entity.player.render(Store.Graphics.SB);
}
Just one thing we need to add to fix very weird problem is to add the following code
Store.Graphics.SB.setProjectionMatrix(Store.Camera.Camera.combined);
so we would have
public void render() {
Store.Graphics.SB.setProjectionMatrix(Store.Camera.Camera.combined);
Store.Graphics.tiledMapRenderer.render();
Store.Entity.player.render(Store.Graphics.SB);
}
That means we need to set projection matrix to current active SpriteBatch to properly render stuff. It's also safe to set it before even render the tile as it uses the same camera as of player.

Related

Making A Sprite Bounce Off The Edge

I'm trying to make a sprite bounce off the edge of the screen when it is less than 0. Right now it just zooms across the screen into the void. Here is my code-note that CentipedeBody is a class that extends Sprite. In the render method I call ex.update(); which is an object of the class. Then in between the batch.begin() and batch.end() I have batch.draw(ex,ex.getPosition().x,ex.getPosition().y,ex.getSize().x,ex.getSize().y);
public class CentipedeBody extends Sprite
{
public CentipedeBody(TextureRegion image,Vector2 position,Vector2 size) {
super(new TextureRegion(image));
this.position = position;
this.size=size;
bounds=new Rectangle(position.x,position.y,8,8);
left=true;
}
public void update() {
bounds.set(getPosition().x,getPosition().y,8,8);
if (left==true) {
position.x-=(.5f);
up=false;
down=false;
right=false;
left=true;
}
if (right==true) {
position.x+=.5f;
left=false;
right=true;
down=false;
up=false;
}
if (down==true) {
position.y-=(.5f);
right=false;
left=false;
down=true;
up=false;
if(position.x<0)
{
left=false;
right=true;
}
}
}
why bounds in your child class, Sprite having already bounds, use that if you're interested in collision with other objects. Same for position and for size, I don't think you need these extra data member in your Child class, use parent x,y for position and width and height for dimension.
public class CentipedeBody extends Sprite {
enum State{
LEFT,RIGHT,DOWN
}
State currentState,previousState ;
public static final float DOWN_MOVEMENT=50;
public float downMovCounter;
public float speed;
public CentipedeBody(TextureRegion image, Vector2 position, Vector2 size) {
super(new TextureRegion(image));
setPosition(position.x,position.y);
setSize(size.x,size.y);
currentState=State.LEFT;
previousState=State.LEFT;
speed=50;
}
public void update() {
float delta=Gdx.graphics.getDeltaTime();
if(currentState ==State.LEFT){
setPosition(getX()-speed*delta,getY());
if(getX()<0) {
previousState=currentState;
currentState = State.DOWN;
}
}
if(currentState ==State.RIGHT){
setPosition(getX()+speed*delta,getY());
if(getX()> Gdx.graphics.getWidth()-getWidth()) {
previousState=currentState;
currentState = State.DOWN;
}
}
if(currentState ==State.DOWN){
setPosition(getX(),getY()+speed*delta);
downMovCounter++;
if(downMovCounter>DOWN_MOVEMENT){
downMovCounter=0;
currentState =previousState==State.LEFT?State.RIGHT:State.LEFT;
}
}
}
}
In render method
batch.begin();
batch.draw(centipedeBody,centipedeBody.getX(),centipedeBody.getY(),centipedeBody.getWidth(),centipedeBody.getHeight());
batch.end();
centipedeBody.update();
May be you need bounds, size and position in CentipedeBody, I can't judge your game requirement by one class code so you can easily integrate your variable in my code.

LibGDX ViewPort keeps squaring up the viewport

Can anyone shed some light on this behaivor of the viewport or ortographic camera? I expect a rectangular viewport to be drawn but what I get instead is everything squeezed up in a square frame. I uploaded a picture to show you what's going on. The center of the green circle is being drawn on to the point(100,100) so clearly , it looks too disproportioned. The size of the red square is supposed to be 400x400 but judging by the way it looks, it isn't . The aspect ratio is completely off. I don't know what's causing this issue. Ignore the little mario in the center. that's being rendered by another camera soewhere else.
Does any one know what could be causing it?
/**
* Created by Omer on 11/24/2015.
*/
public class Play extends GameStateBase {
public static final int CAMERA_TYPE_SCREEN = 0;
public static final int CAMERA_TYPE_MAP = 1;
private Viewport SCREEN_VIEW;
private Viewport MAP_VIEW;
private OrthographicCamera SCREEN_CAM;
private OrthographicCamera MAP_CAM;
AssaultTrooper assaultTrooper;
GamePad GAME_PAD;
public Play(GameStateManager _gameStateManager) {
super(_gameStateManager);
SCREEN_CAM = new OrthographicCamera();
SCREEN_VIEW = new FitViewport(GameGraphics.VIRTUAL_WIDTH,GameGraphics.VIRTUAL_HEIGHT,SCREEN_CAM);
SCREEN_VIEW.apply();
SCREEN_CAM.translate(GameGraphics.VIRTUAL_WIDTH/2,GameGraphics.VIRTUAL_HEIGHT/2);
SCREEN_CAM.update();
MAP_CAM = new OrthographicCamera();
MAP_VIEW = new FitViewport(GameGraphics.VIRTUAL_HEIGHT,GameGraphics.VIRTUAL_HEIGHT,MAP_CAM);
MAP_VIEW.apply();
MAP_CAM.translate(GameGraphics.VIRTUAL_HEIGHT/2,GameGraphics.VIRTUAL_HEIGHT/2);
MAP_CAM.update();
RENDER_STATE.addCamera(CAMERA_TYPE_SCREEN,SCREEN_CAM);
RENDER_STATE.addCamera(CAMERA_TYPE_MAP,MAP_CAM);
GAME_PAD = new GamePad();
RenderStateManager.changeGameRenderState(RENDER_STATE);
GAME_PAD.setCameraType(CAMERA_TYPE_SCREEN);
GAME_PAD.addToRenderState();
assaultTrooper = new AssaultTrooper(GameSettings.TEAM_BLUE,new Location(200,200));
assaultTrooper.setCameraType(CAMERA_TYPE_MAP);
assaultTrooper.addToRenderState();
}
#Override
public void render(SpriteBatch _spriteBatch) {
try {
RenderStateManager.RENDERING_STATE.render(_spriteBatch);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void handleInput() {
}
#Override
public void update(float deltaTime) {
}
#Override
public void dispose() {
}
#Override
public void reSize(int _width, int _height) {
SCREEN_VIEW.update(_width,_height);
MAP_VIEW.update(_width,_height);
}
}
private ConcurrentHashMap<Long,Location> locations;
private ConcurrentHashMap<Long,Sprite> sprites;
private ConcurrentHashMap<Integer,OrthographicCamera> cameras;
private ConcurrentHashMap<Integer,List<Long>> cameraMapping;
public void render(SpriteBatch _spriteBatch) throws InterruptedException {
synchronized (this) {
for (int key : cameras.keySet()) {
_spriteBatch.setProjectionMatrix(cameras.get(key).combined);
_spriteBatch.begin();
if (cameraMapping.get(key) == null) {
_spriteBatch.end();
continue;
}
for (long MAPPER : cameraMapping.get(key)) {
sprites.get(MAPPER).draw(_spriteBatch);
}
_spriteBatch.end();
}
}
}

Bitmap.getPixel in SurfaceView

I have this code where there is a Backgroung under an Hand, both a Bitmap images. Now, i have to control with an onClick method if the click touches the hand or not. For this, i wrote here and some guys tell me to use a method called "bitmap.getPixel(int x, int y)" that gives the color of pixel touched. For control if the click doesn't touch the hand, i write "bitmap.getPixel(x, y) != Color.TRASPARENT", but doesn't work perfectly. Under this i write the code of SurfaceView.
P.S. The bitmap "Hand" is a picture of a central Hand with parts trasparent around.
public class GamePanel extends SurfaceView implements SurfaceHolder.Callback{
private long missileStartTime;
private ThreadLv1 thread;
private OggettiLv1 hand;
private int conto=0;
private Sfondo sfondo;
MediaPlayer ouch;
public GamePanel(Context context){
super(context);
getHolder().addCallback(this);
thread = new ThreadLv1(getHolder(), this);
setFocusable(true);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){}
#Override
public void surfaceDestroyed(SurfaceHolder holder){
boolean retry = true;
while(retry)
{
try{thread.setRunning(false);
thread.join();
}catch(InterruptedException e){e.printStackTrace();}
retry = false;
}
}
#Override
public void surfaceCreated(SurfaceHolder holder){
hand = new OggettiLv1(BitmapFactory.decodeResource(getResources(), R.drawable.mano5));
sfondo = new Sfondo(BitmapFactory.decodeResource(getResources(), R.drawable.sfondo));
ouch= MediaPlayer.create(getContext(), R.raw.ouch);
knifesong.start();
thread.setRunning(true);
thread.start();
}
public void update() {
}
#Override
public void draw(Canvas canvas)
{
if(canvas!=null) {
final int savedState = canvas.save();
background.draw(canvas);
hand.draw(canvas);
drawText(canvas);
canvas.restoreToCount(savedState);
}
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
float x = event.getX();
float y = event.getY();
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
int c = hand.sprite.getPixel((int) event.getX(), (int) event.getY());
if(c!=Color.TRANSPARENT){
conto++;
}
return true;
}
return false;
}
}
Someone know the problem and the solution in this code? Thanks in advance.
I think this might be the problem:
int c = hand.sprite.getPixel((int) event.getX(), (int) event.getY());
I think you are getting the value of a pixel at the x,y location on the sprite, you should get the value of the pixel on canvas.
EDIT:
Since your canvas is static, I suggest doing the following:
add a Bitmap to your class
private Bitmap canvasState;
In the draw function, initialize canvasState before anything else
canvasState = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.RGB_565));
canvas.setBitmap(canvasState);
after that, every change that you make to the canvas will be made to the canvasState, and you can use that in your event handler like so:
int c = canvasState.getPixel((int) event.getX(), (int) event.getY());
I'm not sure if the code I wrote will compile (I wrote them from the top of my head) but I think you can work out compile errors yourself.

LibGDX Bouncing ball

I want to create an infinite bouncing ball. For now I'm just trying to make the bouncing on Y (up & down).
This is my GameWorld class, you can see there is a method collides to detect the collision but How to make that "circle" go up?
public class GameWorld {
private Circle rond;
private Rectangle rect;
public GameWorld(int midPointY) {
rond = new Circle(100, midPointY - 5, 5);
rect = new Rectangle(0, 200, Gdx.graphics.getWidth(), 5);
}
public void update(float delta) {
if(collides(rond)){
}else
rond.y++;
}
public boolean collides(Circle rond) {
if (rect.y < rond.y + (rond.radius)*2) {
return (Intersector.overlaps(rond, rect));
}
return false;
}
public Circle getRond() {
return rond;
}
public Rectangle getRect() {
return rect;
}
}
Of course, I have another class GameRenderer that rendere these two objects
Typically with any kind of physics you want to store the speed of an object as well as its position. That way, each time though your update loop you just have to change the y position by the y speed. When the collision occurs, all you need to do is calculate the new yspeed and update rond.
public void update(float delta) {
if(collides(rond)){
rond.yspeed = -rond.yspeed;
}else{
rond.y+=rond.yspeed*delta;
}
}

LibGDX - IllegalArgumentException causes my game to crash whenever my main character touches a Coin

Trying to figure out why my Android game crashes whenever the player touches an animated coin. I have attached an image of the LogCat and my code is below (NOTE: all game objects in ![Renderer] are in an arraylist called toRender. the 2 coins in the game are currently held in the 3rd and 4th position in the list). Renderer and Coin classes respectively:
public class Renderer extends ApplicationAdapter {
private SpriteBatch batch;
private Texture background;
private ArrayList<GameObject> toRender;
private Timer timer;
private float delta;
private Game game;
public Renderer(ArrayList<GameObject> toRender) {
batch = new SpriteBatch();
background = new Texture(Gdx.files.internal("background2.png"));
this.toRender = toRender;
timer = Timer.getInstance();
}
public void collect() {
// for every object in toRender (an arraylist of objects)
for (GameObject o : toRender) {
// if player collides with/collects an object
if (Player.getInstance(null).hasCollected(o)) {
// if its the first coin that he collides with, dispose it
if (o.equals((Coin) toRender.get(3))) {
((Coin) toRender.get(3)).dispose();
}
// if its the second coin that he collides with, dispose it
if (o.equals((Coin) toRender.get(4))) {
((Coin) toRender.get(4)).dispose();
}
}
}
}
public void beginRendering() {
delta = Timer.getInstance().getTime();
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(background, 0, 0, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight());
timer.drawTime(batch);
for (GameObject object : toRender) {
object.update();
boolean objectIsntCoin = !(object.equals(toRender.get(3)) ||
object.equals(toRender.get(4))); //the 2 coins are in the 3rd and 4th position in the array list
// draw every object's sprite apart from coin, since coin should render the animation rather than the sprite
if (objectIsntCoin) {
object.draw(batch);
}
}
collect();
((Flag) toRender.get(toRender.size() - 1)).drawLevelComplete(batch);
// if the coin exists (i.e. hasn't been disposed), render the animation
if (((Coin) toRender.get(3)).checkExists()) {
((Coin) toRender.get(3)).render(delta);
}
// if the coin exists (i.e. hasn't been disposed), render the animation
if (((Coin) toRender.get(4)).checkExists()) {
((Coin) toRender.get(4)).render(delta);
}
batch.end();
}
}
public class Coin extends GameObject implements Screen {
private SpriteBatch batch;
private Animation animation;
private float time;
private float xPos;
private float yPos;
private Rectangle objectRect;
private boolean exists;
public Coin(Sprite spr, float xPos, float yPos, float radius) {
super(spr, xPos, yPos, radius);
this.xPos = xPos;
this.yPos = yPos;
batch = new SpriteBatch();
objectRect = new Rectangle(getxPos(), getyPos(), getSprite().getWidth(), getSprite().getHeight());
exists = true;
time = 0;
show();
}
public Rectangle getRect() {
return objectRect;
}
public void render(float delta) {
// TODO Auto-generated method stub
batch.begin();
batch.draw(animation.getKeyFrame(time += delta), xPos, yPos);
batch.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
animation = new Animation(1 / 8f,
new TextureRegion(new Texture(Gdx.files.internal("coin1.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin2.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin3.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin4.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin5.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin6.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin7.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin8.png"))));
animation.setPlayMode(Animation.PlayMode.LOOP);
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
batch.dispose();
exists = false;
}
public boolean checkExists() {
return exists;
}
}
LogCat:1
So the errors that the LogCat point to:
1)dispose() method in Coin:
batch.dispose();
2)collect() method in Renderer:
if(o.equals((Coin) toRender.get(3))) {
3)beginRendering() method in Renderer:
for (GameObject object : toRender) {
Does anyone know why my program is crashing? I just want the animated coin to disappear when the Player touches it. Currently the coin DOES disappear, the application just shuts down immediately after though. Have been stuck on this for a while so any insight is highly appreciated.
Thank you in advance.
First, I want to mention that downcasting the objects in toRender like you are is both dangerous and indicates there is a flaw in your design. Additionally, you'll notice that equals(Object) accepts an Object as an argument; you don't need to cast it to Coin.
Anyway, the reason your program is crashing is explained in the IllegalArgumentException message,
buffer not allocated with newUnsafeByteBuffer or already disposed.
You're trying to dispose your Coin's batch when it has already been disposed.
In your collect() method, you loop through the objects, and you dispose of their batches, but the Coin objects themselves are never removed from your toRender list. So, the next time collect() is called, it will loop through those same Coin objects and try to dispose of them again, and an exception is thrown.
The solution is to remove the Coin objects from your toRender list when they no longer belong in your game's scene. However, you can't remove an element from a list while you're iterating over it, as this would disrupt the loop. Instead, remove them like so:
public void collect() {
// Holds the Coins we want to remove from toRender
final Collection<GameObject> toRemove = new LinkedList<>();
for (GameObject o : toRender) {
if (Player.getInstance(null).hasCollected(o)) {
if (o.equals(toRender.get(3))) {
final Coin coin = (Coin) toRender.get(3);
coin.dispose();
toRemove.add(coin);
}
if (o.equals(toRender.get(4))) {
final Coin coin = (Coin) toRender.get(4);
coin.dispose();
toRemove.add(coin);
}
}
}
// Remove the collected Coins
toRender.removeAll(toRemove);
}

Categories