Android - AndEngine Apply Force - java

I'm using AndEngine and Box2d in android application.
What do I have to do so that when pushing the "leftArrow" and "rightArrow" buttons, the player doesn't start moving too fast because of the too frequent call of the "Update Handler" method? I want the player to move constantly with the same speed.
//same for leftArrow
Sprite rightArrow = new Sprite(...) {
#Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
float pTouchAreaLocalX, float pTouchAreaLocalY) {
if(pSceneTouchEvent.isActionDown()) {
goRight = true;
}
else if(pSceneTouchEvent.isActionUp()) {
goRight = false;
}
return true;
}
};
private IUpdateHandler UpdateHandler = new IUpdateHandler(){
#Override
public void onUpdate(float pSecondsElapsed) {
if(goLeft) {
playerBody.applyForce(-50, 0, body.getWorldCenter().x, body.getWorldCenter().y);
}
if(goRight){
playerBody.applyForce(50, 0, body.getWorldCenter().x, body.getWorldCenter().y);
}
}
};

use setLinearVelocity instead of applyForce. It should work

Related

JavaFX How do you bind an animation to a certain value?

I have made an application with JavaFX, where you have a picture with animated stuff in it, based on certain values in the app. The only problem I have: I don't really know, how to bind the values to the animations, so the animations move, based on the value put in. For example: if the value is 10, the animation should move fast. If the value is 1 the animation should move slow. Here is the code for the animation (it is smoke, coming out of a house):
smoke = new Image(HydroControl.class.getResource("/imgs/smoke.png").toExternalForm());
smokeView = new ImageView(smoke);
smokeView.setX(-190);
smokeView.setY(60);
Path path3 = new Path();
path3.getElements().add(new MoveTo(1,-60));
path3.getElements().add(new CubicCurveTo(0, 0, 0, 0, 0, 0));
PathTransition pathTransition3 = new PathTransition();
pathTransition3.setDuration(Duration.millis(2000));
pathTransition3.setPath(path3);
pathTransition3.setNode(smokeView);
pathTransition3.setCycleCount(Timeline.INDEFINITE);
pathTransition3.setAutoReverse(true);
pathTransition3.play();
Here is the code with the values:
public class PresentationModel {
private final DoubleProperty waterValue = new SimpleDoubleProperty();
private final DoubleProperty powerValue = new SimpleDoubleProperty();
private final BooleanProperty isOnValue = new SimpleBooleanProperty();
public double getWaterValue() {
return waterValue.get();
}
public DoubleProperty waterValueProperty() {
return waterValue;
}
public void setWaterValue(double waterValue) {
this.waterValue.set(waterValue);
}
public double getPowerValue() {
return powerValue.get();
}
public DoubleProperty powerValueProperty() {
return powerValue;
}
public void setPowerValue(double powerValue) {
this.powerValue.set(powerValue);
}
public boolean isIsOnValue() {
return isOnValue.get();
}
public BooleanProperty isOnValueProperty() {
return isOnValue;
}
public void setIsOnValue(boolean isOnValue) {
this.isOnValue.set(isOnValue);
}
}
I would be really glad if you could help me. Thank you.
Bind the properties of your transition to the values of your model with a calculation from the Bindings class. For example:
pathTransition3.durationProperty().bind(Bindings.multiply(Bindings.multiply(model.powerProperty(), model.waterValueProperty()), 500d));
model.isOnValueProperty().addListener((v, o, n) -> {
if (n) {
pathTransition3.play();
} else {
pathTransition3.pause();
}
});

Libgdx Ending level is not working properly

In my game the kid is collecting fruits but if he hits the rock 3 times or time is up before collecting the required points, the kid will jump to the half of the screen then fall down and start fail music then move to game over screen but I have two problems here:
when time is up the boy jump to top and continue out of the screen not the bottom and the music of fail is slow and choppy.
when kid hits rock 3 times it start fail music well and jump to the center of screen and fall down out of the screen from bottom and this is very good then go to game over screen, but when i go back from game over screen,the music of the Play screen is not working:
here is the code :
public boolean Rockhit()
{
if(Rocks.isRock) {
rocknum--;
Hud.collectorLives(rocknum);
Rocks.isRock=false;
if (rocknum == 0)
return true;
else
return false;
}
else
Hud.collectorLives(rocknum);
return false;
}
public State getState()
{
//Gdx.app.log(Float.toString(b2body.getLinearVelocity().x),"hi");
if ((Hud.getTime()==0&& Hud.getScore()<(level*30)+50)) {
Fruits.manager.get("music/Backmusic.ogg", Music.class).stop();
collectoIsDead=true;
Filter filter = new Filter();
filter.maskBits = Fruits.NOTHING_BIT;
for (Fixture fixture : b2body.getFixtureList())
fixture.setFilterData(filter);
b2body.applyLinearImpulse(new Vector2(0, 5f), b2body.getWorldCenter(), true);
//b2body.applyLinearImpulse(new Vector2(0,-2.5f), b2body.getWorldCenter(), true);
Fruits.manager.get("music/fail.mp3", Sound.class).play();
return State.DEAD;
}
if ( Rockhit()) {
Fruits.manager.get("music/Backmusic.ogg", Music.class).stop();
collectoIsDead=true;
Filter filter = new Filter();
filter.maskBits = Fruits.NOTHING_BIT;
for (Fixture fixture : b2body.getFixtureList())
fixture.setFilterData(filter);
b2body.applyLinearImpulse(new Vector2(0, 5f), b2body.getWorldCenter(), true);
//b2body.applyLinearImpulse(new Vector2(0,-2.5f), b2body.getWorldCenter(), true);
Fruits.manager.get("music/fail.mp3", Sound.class).play();
return State.DEAD;
}
if((Hud.getTime()==0&& Hud.getScore()>=(level*30)+50)|| (Hud.getScore()>=(level*30)+50)) {
Fruits.manager.get("music/Backmusic.ogg", Music.class).stop();
Fruits.manager.get("music/cheering.mp3", Sound.class).play();
return State.SUCCESS;
}
this is the code of gameover screen:
public class GameOverScreen implements Screen {
private Viewport viewport;
private Stage stage;
private Fruits game;
private float level;
public GameOverScreen(Fruits game,float level)
{
this.level=level;
this.game=game;
viewport=new FitViewport(Fruits.V_WIDTH,Fruits.V_HIEGT,new OrthographicCamera());
stage=new Stage(viewport,((Fruits) game).batch);
Label.LabelStyle font = new Label.LabelStyle(new BitmapFont(), Color.WHITE);
Table table=new Table();
table.center();
table.setFillParent(true);//the table will take all the stage
Label gameOverLabel = new Label("Game Over",font);
Label playAgainLabel = new Label("Click Here",font);
table.add(gameOverLabel).expandX();
table.row();
table.add(playAgainLabel).expandX().padTop(10f);// make it bellow Game over text by 10 pixels
stage.addActor(table);
}
#Override
public void render(float delta) {
if(Gdx.input.isTouched()) {
game.setScreen(new Worlds(game,level));
dispose();
}
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.draw();
}
#Override
public void show() {
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
}
here where I am processing the state of the kid in the play screen:
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
kid.draw(batch);
if(gameOver())//24
{
gameisover=true;
globalcounter--;
Gdx.app.log(Float.toString(globalcounter), "counter");
if(globalcounter==0) {
game.setScreen(new GameOverScreen(game, level));
dispose();
}
}
if(gameisover==true) {
globalcounter--;
Gdx.app.log(Float.toString(globalcounter), "counter");
if (globalcounter == 0) {
game.setScreen(new GameOverScreen(game, level));
dispose();
}
}
if(nextLevel())
{
prefs = Gdx.app.getPreferences("levels");
String name=prefs.getString("level", " ");
if(name==" ") {
prefs.putString("level", Float.toString(level + 1));
prefs.flush();
}
else {
prefs.putString("level", Float.toString(level+1));
prefs.flush();
}
game.setScreen(new Celebration(game,level+1));
dispose();
}
}
public boolean gameOver()//25
{
if(player.currentState== Collector.State.DEAD )// will show the game over screen after 3 seconds
{
return true;
}
return false;
}
public boolean nextLevel()//25
{
if(player.currentState== Collector.State.SUCCESS)// will show the game over screen after 3 seconds
{
return true;
}
return false;
}
Well, to start off with, your structure is flawed.
Your getState does not just return a state. A lot of things are happening before you return a state. You should really move those things and do them AFTER you have changed state.
I don't see a State.PLAYING? You only have 2 states DEAD and SUCCESS
You stop your background music:
Fruits.manager.get("music/Backmusic.ogg", Music.class).stop();
But it looks like you never start it again.

libGDX - Button is set to down even if outside of bounds

I'm am trying to properly setup button clicks for my UI. I want my buttons to respond right after clicking them instead of releasing by using ClickListeners touchDown method.
I've created a class which creates and displays a table with text input:
public class InputBox {
public static float OFFSET = 20;
private Table table;
private TextField inputField;
private TextButton okButton;
private TextButton closeButton;
private String saveText;
private TextButtonStyle style;
private Skin skin;
public InputBox(Skin skin, float x, float y, float width, float height, boolean visible) {
this.skin = skin;
table = new Table();
// Creating a new style as suggested.
style = new TextButtonStyle();
style.up = skin.getDrawable("button_normal_up");
style.down = skin.getDrawable("button_normal_down");
style.font = skin.getFont("default");
inputField = new TextField("", skin);
okButton = new TextButton("Ok", style);
okButton.addListener(new ClickListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if (button != Buttons.LEFT) {
return false;
}
Game.resources.getSound("click_2").play();
table.setVisible(false);
if (inputField.getText().equals("")) {
saveText = null;
return false;
}
saveText = inputField.getText();
return true;
}
});
closeButton = new TextButton("Close", style);
closeButton.addListener(new ClickListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if (button != Buttons.LEFT) {
return false;
}
Game.resources.getSound("click_2").play();
saveText = null;
table.setVisible(false);
return true;
}
});
table.setVisible(visible);
table.setX(x);
table.setY(y);
table.setWidth(width);
table.setHeight(height);
table.add(inputField).colspan(2).center().width(width - OFFSET).expand().padRight(2);
table.row();
table.add(okButton).width(width / 2 - OFFSET / 2).right();
table.add(closeButton).width(width / 2 - OFFSET / 2).left();
table.pad(5);
}
public void setUnclicked() {
style.down = skin.getDrawable("button_normal_up");
// I think these two lines ar uneeded.
okButton.setStyle(style);
closeButton.setStyle(style);
}
public void setClicked() {
style.down = skin.getDrawable("button_normal_down");
// Same here.
okButton.setStyle(style);
closeButton.setStyle(style);
}
public void setText(String text) {
inputField.setText(text);
}
public String getSaveTextOnce() {
String temp = saveText;
saveText = null;
return temp;
}
public void setBackground(Drawable background) {
table.setBackground(background);
}
public boolean isVisible() {
return table.isVisible();
}
public void setVisible(boolean visible) {
table.setVisible(visible);
}
public Table getTable() {
return table;
}
}
The table is being set to visible after clicking a different button:
// Save map button.
saveMap = new ImageButton(new ImageButtonStyle());
saveMap.getStyle().imageUp = uiSkin.getDrawable("save");
saveMap.getStyle().up = uiSkin.getDrawable("button_flat_up");
saveMap.getStyle().down = uiSkin.getDrawable("button_flat_down");
saveMap.addListener(new ClickListener() {
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if (button != Buttons.LEFT) {
return false;
}
Game.resources.getSound("click_2").play();
if (saveBox.isVisible()) {
saveBox.setVisible(false);
saveBox.setUnclicked();
return false;
}
saveBox.setVisible(true);
saveBox.setClicked();
return true;
}
});
The entire class for the saveMap button: http://pastebin.com/62ZGfcch
However, if I close the table by clicking the "ok" or "close" button and click and hold the mouse over the show table button, the table reappears with last clicked button being held down.
This video illustrates whats happening:
https://www.youtube.com/watch?v=Jf3WzU8G4dE&feature=youtu.be
If I move the mouse while holding it down, the last clicked button on the table resets to its normal state.
First i would recommend you to rather use a TextButtonStyle instance for setting the style of the buttons rather than a Skin instance.
You could somehow get the TextButton's references to the saveMap.addListener anonymous inner class. Then you could manualy set the style of the Ok and Cancel TextButton's, something like this:
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
Game.resources.getSound("click_2").play();
if (saveBox.isVisible()) {
saveBox.setVisible(false);
okButtonReference.setStyle(unclickedTextButtonStyle) // Not-clicked TextButtonStyle as parameter
cancelButtonReference.setStyle(unclickedTextButtonStyle) // Not clicked TextButtonStyle as parameter.
return false;
}
saveBox.setVisible(true);
return true;
}
By forcing the TextButton to change it's TextButtonStyle by calling setStyle() you can be confident that the button will change.
Also i noticed that you are not calling the debug() method on the Table object. This is not necessary but it is advisable:
table.add(inputField).colspan(2).center().width(width - OFFSET).expand().padRight(2);
table.row();
table.add(okButton).width(width / 2 - OFFSET / 2).right();
table.add(closeButton).width(width / 2 - OFFSET / 2).left();
table.pad(5);
table.debug();
After more fiddling I found out that the way I setup my games InputProcessor was causing this issue. I did not handle the touchUp event properly.
Game.inputs.addProcessor(new InputProcessor() {
...
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
releasedButton = -1;
if (UI.isOver()) {
return false;
}
if (button == Buttons.LEFT) {
releasedButton = Buttons.LEFT;
}
if (button == Buttons.RIGHT) {
releasedButton = Buttons.RIGHT;
}
return true; // <--- setting this to false fixes the issue
}
});

How to execute function ONLY after all actions are finished in Cocos2d

Can you guys tell me how can I execute function updateTiles() ONLY after all nodes' actions in function slideTiles(String s) are finished? I tried adding some while loop but it freezes whole program. After running functions one after another the animations just don't show up.
public boolean ccTouchesEnded(MotionEvent event)
{
CGPoint location = CCDirector.sharedDirector().convertToGL(CGPoint.ccp(event.getX(), event.getY()));
x2=location.x; y2=location.y;
float diffY = y1-y2;
float diffX = x1-x2;
if (Math.abs(diffX)>Math.abs(diffY)&&diffX<0)
move="right";
else if (Math.abs(diffX)>Math.abs(diffY)&&diffX>=0)
move="left";
else if (Math.abs(diffX)<=Math.abs(diffY)&&diffY<0)
move="up";
else if (Math.abs(diffX)<=Math.abs(diffY)&&diffY>=0)
move="down";
int row=(int)(y1/TILE_SQUARE_SIZE);
int column=(int)(x1/TILE_SQUARE_SIZE);
slideTiles(move);
//wait for animations to finish
int sum=0;
boolean actionDone=false;
while (!actionDone)
{
for (CCNode c : tilesNode.getChildren())
{
sum+=c.numberOfRunningActions();
}
//String s=sum+"";
//statusLabel.setString(s);
if (sum==0){
actionDone=true;
break;
}
sum=0;
}
updateTiles();
return true;
}
//////
public void slideTiles(String move)
{
// Increment the moves label and animate the tile
CCBitmapFontAtlas moveslabel = (CCBitmapFontAtlas) getChildByTag(MOVES_LABEL_TAG);
moves++;
moveslabel.runAction(CCSequence.actions(
//CCDelayTime.action(0.25f),
CCScaleTo.action(0.2f, 6/5f),
//CCDelayTime.action(0.25f),
CCScaleTo.action(0.2f, 5/6f)
));
moveslabel.setString("Moves:\n " + CCFormatter.format("%03d", moves ));
if (move.equals("up"))
{
for (int start=NUM_COLUMNS; start<2*NUM_COLUMNS; start++)
for (int y=start; y<NUM_COLUMNS*NUM_ROWS; y+=NUM_COLUMNS)
{
if (tileNumbers[y]!=EMPTY)
{
for (int f=start-NUM_COLUMNS; f<y; f+=NUM_COLUMNS)
{
if (tileNumbers[f]==EMPTY)
{
//y->f
CGPoint moveTo = tilesNode.getChildByTag(f).getPosition();
CCMoveTo movetile = CCMoveTo.action(0.25f, moveTo);
CCSequence movetileSeq = CCSequence.actions(movetile);//CCCallFunc.action(this,"stopAction"));
tilesNode.getChildByTag(y).runAction(movetileSeq);
tileNumbers[f]=tileNumbers[y];
tileNumbers[y]=EMPTY;
break;
}
}
}
}
}
Edit: Is this kind of solution correct? It works surprisingly well.
public boolean ccTouchesEnded(MotionEvent event)
{
...
...
slideTiles(move);
float time = 0.25f+0.05f; //0.25f is time of moveTo action for each tile
CCDelayTime delay = CCDelayTime.action(time);
CCCallFunc cA = CCCallFunc.action(this, "updateTiles");
CCSequence se = CCSequence.actions(delay, cA);
runAction(se);
return true;
}
Generally, you shouldn't use while loop to wait in UI thread , it will cause big problem you have saw it.
You should use Thread to do this waiting job.
new Thread(new Runnable() {
#Override
public void run() {
while(true){
//here you wait forever doesn't matter the UI thread.
if(everythingDone) {//here to add your condition
new Handler().post(new Runable() {
#Override
public void run() {
//Here you can do what you want and will be done in UI Thread
}
});
}
}
}
}).start();

GameLoop Thread occasionally slow

For the game I'm currently writing for Android devices, I've got a class called RenderView, which is a Thread and updates and renders everything. Occasionally the class logs the message "Game thread is only updating the update method and is not rendering anything". The game is running at 30 fps on my nexus s. And I get the message a couple of times throughout the session. Could someone tell me how I could optimize the class or if I'm forgetting something or that it's totally normal?
Here's my code:
public class RenderView extends SurfaceView implements Runnable {
public final String classTAG = this.getClass().getSimpleName();
Game game;
Bitmap framebuffer;
Thread gameloop;
SurfaceHolder holder;
boolean running;
int sleepTime;
int numberOfFramesSkipped;
long beginTime;
long endTime;
long lastTime;
int differenceTime;
int framePeriod;
Canvas canvas;
int frameCount;
WSLog gameEngineLog;
public RenderView(Game game, Bitmap framebuffer) {
super(game);
this.game = game;
this.framebuffer = framebuffer;
this.holder = getHolder();
framePeriod = 1000/game.getFramesPerSecond();
lastTime = System.currentTimeMillis();
gameEngineLog = game.getGameEngineLog();
}
#Override
public void run() {
while(running == true) {
if(holder.getSurface().isValid()) {
beginTime = System.currentTimeMillis();
numberOfFramesSkipped = 0;
game.getCurrentScreen().update();
game.getCurrentScreen().render(); // Draw out everything to the current virtual screen (the bitmap)
game.getGraphics().renderFrameBuffer(); // Actually draw everything to the real screen (combine both bitmaps)
canvas = holder.lockCanvas();
if(canvas != null) { // Fix for mysterious bug ( FATAL EXCEPTION: Thread)
// The viewing area of our virtual screen on our real screen
canvas.drawBitmap(framebuffer, null, game.getWSScreen().getGameScreenextendeddst(), null);
holder.unlockCanvasAndPost(canvas);
}
else {
gameEngineLog.e(classTAG, "Surface has not been created or otherwise cannot be edited");
}
endTime = System.currentTimeMillis();;
differenceTime = (int) (endTime - beginTime);
sleepTime = (int) (framePeriod - differenceTime);
if(sleepTime > 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException exception) {
exception.printStackTrace();
}
}
else {
while(sleepTime < 0 && numberOfFramesSkipped < game.getMaxFrameSkippes()) {
gameEngineLog.d(classTAG, "Game thread is only updating the update method and is not rendering anything");
try {
Thread.sleep(5);
}
catch (InterruptedException exception) {
exception.printStackTrace();
}
game.getCurrentScreen().update();
sleepTime += framePeriod;
numberOfFramesSkipped++;
}
}
// Frame Per Second Count
frameCount++;
if(lastTime + 1000 < System.currentTimeMillis()) {
game.getGameEngineLog().d(classTAG, "REAL FPS: " + frameCount);
lastTime = System.currentTimeMillis();
frameCount = 0;
}
}
}
}
public void resume() {
running = true;
gameloop = new Thread(this);
gameloop.start();
}
public void pause() {
running = false;
while(running == true) {
try {
gameloop.join();
running = false;
}
catch (InterruptedException e) {
}
}
gameloop = null;
}
}
Here's the code for the Graphics class (the getGraphics() just return an graphics object):
public class Graphics {
public final String classTAG = this.getClass().getSimpleName();
Game game;
Canvas frameBuffer;
Canvas canvasGameScreenextended;
Canvas canvasGameScreen; // Used for customeScreen
Bitmap gameScreenextended;
Bitmap gameScreen;
Rect gameScreendst;
Rect gameScreenextendeddst;
WSLog gameEngineLog;
Graphics(Game game, Bitmap framebuffer, Bitmap gameScreen) {
this.game = game;
// Initialize canvases to render to
frameBuffer = new Canvas(framebuffer);
canvasGameScreen = new Canvas(gameScreen);
// Initialize images to be rendered to our composition
this.gameScreen = gameScreen;
// Set up the Log
gameEngineLog = game.getGameEngineLog();
}
public void resetCanvasGameScreenextended() {
// This method has to be called each time the screen scaling type changes
canvasGameScreenextended = new Canvas(game.getWSScreen().getGameScreenextended());
gameScreenextended = game.getWSScreen().getGameScreenextended();
}
public Canvas getCanvasGameScreenextended() {
return canvasGameScreenextended;
}
public Canvas getCanvasGameScreen() {
return canvasGameScreen;
}
public void renderFrameBuffer() {
// Composition
// First layer (bottom)
frameBuffer.drawBitmap(gameScreen, null, game.getWSScreen().getGameScreendst(), null);
// Second layer (top)
frameBuffer.drawBitmap(gameScreenextended, null, game.getWSScreen().getGameScreenextendeddst(), null);
}
public void clearFrameBuffer() {
canvasGameScreen.drawColor(Color.BLACK);
//canvasGameScreenextended.drawColor(Color.BLACK);
gameScreenextended.eraseColor(Color.TRANSPARENT); // Make top layer transparent
}
}
Here's the code for the screen class (the getCurrentScreen() method returns a screen object):
public class Screen {
public final String classTAG = this.getClass().getSimpleName();
protected final Game game;
protected final Graphics graphics;
protected Screen(Game game) {
this.game = game;
this.graphics = game.getGraphics();
//game.getInput().reset();
}
public void update() {
}
public void render() {
}
/** Initialize all the sensory that should be used within this screen.*/
public void resume() {
}
public void pause() {
game.getInput().useAccelerometer(false);
game.getInput().useKeyboard(false);
game.getInput().useTouchscreen(false);
}
public void onDispose() {
game.getGraphics().clearFrameBuffer();
}
public void setScreenResizeType(int screenResizeType) {
}
The Screen class is extended and the render() method is shadowed with methods like:
graphics.getCanvasGameScreen().drawRect(play, red);
The funny thing is, when I override the render() method and don't place any code in it, the logger fires constantly with the message: "Game thread is only updating the update method and is not rendering anything". What kind of sorcery is this?!
Help is hugely appreciated!
As far as I understand from your updated post, there is no rendering problem actually. Instead, your code mistakenly prints that message.
This is because you check if(sleepTime > 0) , so if the rendering is very fast and sleepTime is zero, you get that message. Just change it to if(sleepTime >= 0).

Categories

Resources