Changing deltaTime of libgdx games - kotlin

I want to pause my libgdx game which has box2d word. To pause game I decided manupilate the deltaTime.
I thought that if i assingn deltaTime to zero all rendering codes can wait until press resume button. However deltaTime is not var it is val. So because of deltaTime is val, I am not able to reassign the value of deltaTime. Changing the deltaTime is forbidden. Is there any way to change the deltaTime.

deltaTime is the measurement of the elapsed time since the last render, not a parameter.
You can stop (and start) rendering with
Gdx.graphics.setContinuousRendering(false);
(This is usually used for when you want to determine how often to render with Gdx.graphics.requestRender() )
Note that this will stop all rendering so maybe instead just pause stepping the world in your call.
if (!isPaused) {
box2DWorld.step(TIME_STEP_IN_SECONDS,
VELOCITY_ITERATIONS,
POSITION_ITERATIONS);
}

Related

Box2D collision detection fails after firing a lot of bullets

I am working on a physics game and encountered a strange bug: sometimes, after firing a lot of bullets, collision detection starts to fail.
As can be seen in the following GIF, the collision works only on half the platform, which is very strange. Also, the Box2D debug renderer is enabled and it can also be seen that the platform is a single body.
Here is how I get this bug to happen, as it only happens only after firing lots of bullets (in the beginning everything works fine):
Notes:
- the bullet has the bullet field set to true
- I set the player's bullet field to true, did not make a difference
- the player is 1 meter by 1 meter
- the player and the bullets are DynamicBodies and the platforms are StaticBodies
- the map is near to (0, 0), though it goes a bit in the negatives (-1.5), I doubt it matters
- the categoryBits and maskBits are correct (the collision should happen, and it does happen, but glitches)
- after the bullets disappear, the number of bodies is the same as when the game starts (so they are actually destroyed)
- the World's gravity is (0, -25f)
- the game runs at 60fps
Here is the Box2D timestep code, similar to the stepping code from the libGDX wiki:
companion object {
private const val TIME_STEP = 1f / 300f
private const val VELOCITY_ITERATIONS = 6
private const val POSITION_ITERATIONS = 2
}
private var accumulator = 0f
override fun update(deltaTime: Float) {
accumulator += Math.min(deltaTime, 0.25f)
while (accumulator >= TIME_STEP) {
world.step(TIME_STEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS)
accumulator -= TIME_STEP
}
}
I tried changing:
- TIME_STEP to a lower value, like 1/60f
- VELOCITY_ITERATIONS a bit higher, to 8
- POSITION_ITERATIONS a bit higher, to 6
- VELOCITY_ITERATIONS and POSITION_ITERATIONS to 100
and there was no (obvious) difference.
Concern:
The bugged platform seems to start behaving like a bullet (it doesn't collide with other bullets or with the player), at least halfway. So could its categoryBits and maskBits be changed on-the-fly, after a lot of world.createBody() and world.destroyBody(), maybe due to pooling?
So what should I try for the collision not to fail in this case?
I finally managed to fix it.
The solution I found was to loop through every entity that has a body and call refilter(), which seems to fix it:
engine.getEntitiesFor(Family.one(BodyComponent::class.java).get()).forEach {
it.body.body.fixtureList.first().refilter()
}
In the future, I could call refilter() only when needed (if I can determine when I have to call it) instead of calling it every frame, but it works for now.
It looks like you should call refilter() after you change the filterData of a body (changing its categoryBits or maskBits) outside the FixtureDef, but I don't seem to be doing that (or maybe I am missing something), so it is a bit weird.

How to stop infinite cola layout manually?

I had used infinite option in cola layout to draw the nodes and their connections. I was trying to add manual stop function to this when all the nodes in the graph get well settled. But I couldn't find a way to do this.
So, how can I manually stop the cola layout?
I cannot use max simulation time option as the number of nodes in the graph and their connections can vary and so deciding this time is not possible.
As a hack, I am using currently like
var simulationStopTimer = setInterval(function (){
if (simulationStopNow){
options.infinite = false;
adaptor.stop();
clearInterval(simulationStopTimer);
}
}, 10000);
So, i am using a timer every 10 seconds to check whether the user has clicked a button to stop the layout. Is there is any better way?
If you create a layout object, you can call layout.stop() : http://js.cytoscape.org/#layouts/layout-manipulation/layout.stop
For your case, however, that is unnecessary:
Physics layouts automatically stop once they're settled. Make sure to set your force parameters appropriately. And turn the time limit to a high value so the layout doesn't stop prematurely.

Variable Jump Height

I have been having great difficulty creating a jumping system whereby the user can tap the jump button for a small jump and hold it down for a higher jump.
I stumbled upon this topic:
https://gamedev.stackexchange.com/questions/13277/variable-height-jumping-in-side-scrollers
Which greatly helped me develop the following code:
PlayerMovementTimer = [NSTimer scheduledTimerWithTimeInterval:0.005 target:self selector:#selector(movePlayer) userInfo:nil repeats:YES];
[JumpButton addTarget:self action:#selector(jumpPlayer:) forControlEvents:UIControlEventTouchDown];
[JumpButton addTarget:self action:#selector(stopJump:) forControlEvents:UIControlEventTouchCancel | UIControlEventTouchUpInside | UIControlEventTouchDragExit];
- (void)movePlayer
{
CGFloat playerY = Player.center.y + PlayerYV;
if(playerY > 264) {
PlayerYV = 0;
playerY = 264;
}
if(playerY < 264) {
PlayerYV += 0.048f - PlayerYD;
}
if(HoldingJump && PlayerYV < 0 && PlayerYD + 0.0018f < 0.048f) {
PlayerYD += 0.0018f;
}
Player.center = CGPointMake(Player.center.x + PlayerXV, playerY);
}
- (IBAction)jumpPlayer:(id)sender
{
if(Player.center.y == 264) {
PlayerYD = 0;
PlayerYV = -2.25;
HoldingJump = true;
}
}
- (IBAction)stopJump:(id)sender
{
HoldingJump = false;
}
The code seems to work (some of the values need a bit of fine tuning but I haven't gotten round to that yet). The only problem is that the movement appears to be slightly jerky (even on the real device) and that when the player is at the top of the jump they accelerate really slowly and no values I put seem to be able to get the jump to look smooth like on Mario games.
Please take a look at the code and see if I am missing something obvious, or if there is a more efficient method of controlling movement than an NSTimer calling a void function. Also, is setting a UIImageView's position to a float value bad?
Thanks.
So there are quite a few things wrong here. First, yes, you should never be setting the origin of an ImageView or any other UI element to a coordinate position that is a fractional pixel. This causes sub-pixelling which will blur your image. To avoid this, all CGFloats should be rounded to the nearest whole number using roundf() or other similar rounding functions.
Another issue I can see is that you're setting Player.center. I hope for your sake that Player is not an ImageView cause you're going to be making your life harder. As mentioned above, when the origin of a frame is not set to a CGFloat that is a round number, you'll get sub-pixelling. When you use the center property, you can easily cause yourself to get on a bad origin value. For example, if I have a 11 by 11 image and set it's center to (11,11), the origin will get set to (5.5,5.5) and will cause sub-pixelling. Easy ways to avoid this is just do the math to place the origin correctly and make sure to round the CGFloats that you feed into it (or use CGRectIntegral on the frame before you set it).
A third issue here is that the timer is being called 0.005 seconds. Let's assume you want this game to run with 60 FPS. 60 FPS translates to about 0.0167 seconds. The timer is calling the method three times more often then it would need to even if you wanted 60 FPS and additionally, calling this method so often could be causing some of your jerky motion.
Now in terms of getting a "Mario" like jump, what you really need to do is look at getting a dedicated physics engine since if you're using the code above, you don't appear to have one. What a physics engine would do is it would apply a constant "gravity" which will help make the player jumps look and act more realistically. You would, when a player presses a button, apply an impulse up on the player character. The use of impulses would also simplify your work as you could apply impulses in different ways depending on how long they hold the button, etc. The code above is simply trying to get around this problem instead of addressing the real issue of you not having a physics engine.
Go investigate cocos2D and Box2D as a possible physics engine you could use. There are a wealth of resources on cocos2D+Box2D and there is a developer who even has made a tutorial on using cocos2D to create a Super Mario clone that should give you some basic understanding of how physics engines work: http://www.raywenderlich.com/15230/how-to-make-a-platform-game-like-super-mario-brothers-part-1

Cancelling a setInterval delay while it is running in AS2

Is this possible?
I have a file in which a movie clip is launched when the user roles over another element. To make the user experience more pleasant this happens after a 3 second delay using setInterval. Is there a way of stopping and resetting this time if the user rolls off the element before the 3 seconds is up?
var xTimer = setInterval(wait, 3000);
function wait(){
show('all');
play('all');
clearInterval(xTimer);
}
Above is the code I have used to set the delay, and below is the code I had assumed would interrupt and reset the timer.
invisBtn.onRollOut = function(){
rollover_mc.gotoAndStop(1);
stop();
clearInterval(xTimer());
trace('off');
}
Any help on this would be massively appreciated.
First, the setInterval & clearInterval functions use a Number variable to work.
setInterval() returns a Number variable, and clearInterval() takes that Number in parameter to remove the previous started interval. Here you seem to keep the interval ID inside a function variable instead of a Number one.
Thus, clearInterval(xTimer()); should in reality be clearInterval(xTimer); (without the parenthesis after xTimer).
And secondly, so you can use it in the invisBtn.onRollOut function, just be sure that the xTimer variable is scoped correctly (not inside a function where the invisBtn.onRollOut isn't also), and not on different keyframes of the timeline (timeline keyframes in Flash tends to forget the code you've written on it as soon as the reading head passes onto a new keyframe of the layer which has the code on it).
Feel free to ask more details if you need !

best way to create a timer for a game

I have a time limiter for a game I am doing, what I am doing right now is using an initial value and deducting one value per frame update. here is the code :
- (void) gameTime {
fullTime = fullTime - 1;
NSLog(#"%i", fullTime);
float xScale = 10 * fullTime / 4000;
//_game.timerGraphic.scaleX = 10;
//[_game.timerGraphic setScaleX:10];
[_game.timerGraphic setScaleX:xScale];
}
now the problem is that timerGraphic is a CCSprite, and when I update the ScaleX it doesnt work unless its a absolute value, is there anyway i can make this smoother and resize the "timer" in a smoother way?
The problem with this sort of approach is that is makes the timer in your app dependent on the frame rate. Cocos2D has some built in mechanisms for dealing with these sorts of issues. In particular, the idea is that each time you load a new frame, you update animation values based on the amount of time elapsed between the previous and current frame. Look at the "Making Things Move" section in this Cocos2D tutorial. It explains how to schedule a selector (i.e., create a timer to fire the -nextFrame: method). This method get passed a dt (delta time) argument that can be used for creating smooth animations.