Libgdx Animation run loop only twice - loops

So I'm trying to stop an animation after running twice.
I am playing the animation by setting
Animation blink = new Animation(BLINK_TIME, frames); // parameters are my fields
This is how i get my current frame:
if(animate){
stateTime += Gdx.graphics.getDeltaTime(); //stateTime was initialized to 0
currentFrame.setRegion(blink.getKeyFrame(stateTime, true));
}
else
currentFrame.setRegion(defaultRegion); // again, my own field!
Everything works fine uptill here when the animate field is true.
Now I want to stop the animation, this is what I do for it:
if(blink.isAnimationFinished(stateTime)){
blinkTimes++;
if(blinkTimes>=2)
animate = false;
}
The problem is, isAnimationFinished(stateTime) never gets called. I guess it has to do something with looping animation. Can someone please point me in the right direction?
Thanks!

Found the Problem!
isAnimationFinished(stateTime) does not work when animation is being played in the loop. So, I had to play it in Animation.Normal mode and use false in blink.getKeyFrame(stateTime, false) telling the Animation class to run it in non-loop mode!

Everything seems ok. I think you have initialized
stateTime = 0;
inside the render method or update method where firstly its value = 0 and then you add deltaTime to it.. In the end it never reaches to position where animation gets finished.
I think you should log the value of stateTime when your
if(animate) // log what is your stateTime
And 1 more thing
if(blink.isAnimationFinished(stateTime)){
blinkTimes++;
stateTime = 0 ; //----------- because your animation should start from begining else it will complete 2 cycles in no time.
if(blinkTimes>=2)
animate = false;
}
I hope this helps.. and if i am not getting your question properly just let me know.

Related

Counting number of times a movieclip loops

I have a 20 frame bouncing ball movieclip “ballAnim” on frame 1 of the stage, and I simply want to count each time “ballAnim” loops playback.
I am inexperienced with actionscript, and I’ve searched and tried a few things to no avail.
Here’s the code from my latest attempt:
import flash.events.Event;
var loopCounter:int;
ballAnim.addEventListener(Event.ENTER_FRAME, addOneLoop);
function addOneLoop(e:Event){
if(ballAnim.currentFrame == 20)
{loopCounter+1}
}
trace(loopCounter);\`
All I get is a single instance of 0. I’ve searched around and I think the problem is that loopCounter is resetting to 0 on every frame because of ENTER_FRAME? I tried addressing this by adding a 2nd keyframe on my actions timeline layer with stop(); (with the movieclip layer spanning both frames underneath) but it doesn’t help.
I’ve read that I might need to use a class, but I’m not sure what that is, and I thought this would be a fairly straightforward thing.
Ok, let's have a class.
Your problem is not understanding the flow of things. If we put it simply, Flash Player executes the movie/application in the infinite loop of recurring phases:
Playheads of playing MovieClips (also, the main timeline) move to the next frame.
Frame scripts are executed.
The whole movie is rendered and the picture is updated on the screen.
Pause till the next frame.
Events are handled.
Ok, the exact order just MIGHT be different (it is possible to figure it out but not important now). The important part is to understand that:
Flash Player is (normally) not a multi-thread environment, the phases follow each other, they never overlap, only one thing at a time happens ever and we are pretty much able to follow, which one.
The script you provided is executed at the "frame scripts" phase and that the ENTER_FRAME event handler doesn't execute until the "event handling" phase kicks in.
So, let's check it:
import flash.events.Event;
// This one returns time (in milliseconds) passed from the start.
import flash.utils.getTimer;
trace("A", getTimer());
ballAnim.addEventListener(Event.ENTER_FRAME, addOneLoop);
// Let's not be lazy and initialize our variables.
var loopCounter:int = 0;
function addOneLoop(e:Event):void
{
trace("BB", getTimer());
// Check the last frame like that because you can
// change the animation and forget to fix the numbers.
if (ballAnim.currentFrame >= ballAnim.totalFrames)
{
trace("CCC", getTimer());
// Increment operation is +=, not just +.
loopCounter += 1;
}
}
trace("DDDD", getTimer());
trace(loopCounter);
Now once you run it, you will get something like this:
A (small number)
DDDD (small number)
0
BB ...
BB ...
(20 times total of BB)
BB ...
CCC ...
BB ...
BB ...
Thus, in order to trace the number of loops happened, you need to output it inside the handler rather than in the frame script:
import flash.events.Event;
import flash.utils.getTimer;
ballAnim.addEventListener(Event.ENTER_FRAME, addOneLoop);
var loopCounter:int = 0;
function addOneLoop(e:Event):void
{
if (ballAnim.currentFrame >= ballAnim.totalFrames)
{
loopCounter += 1;
// This is the very place to track this counter.
trace("The ball did", loopCounter, "loops in", getTimer(), "milliseconds!");
}
}

How to break while-loop in VFP (FoxPro) by button click?

I'm trying to make simple FoxPro application with two buttons. First button starts while-loop and works correctly. Second button must break this loop. But I can't find any correctly working solution.
There are loop code:
DO WHILE !thisForm.cancelpressed
IF thisForm.cancelpressed
EXIT
ENDIF
randNum=VAL(TRIM(STR(ROUND( 3*RAND(), 1))))
&&oneVar=VAL("1")
IF randNum = VAL("1")
ThisForm.shape1.BackColor = greenColor
ThisForm.shape2.BackColor = orangeColor
ThisForm.shape3.BackColor = redColor
ENDIF
cs = seconds()
IF abs(cs - seconds()) >= 15
doevents
cs = seconds()
ENDIF
IF thisForm.cancelpressed
EXIT
ENDIF
DOEVENTS
WAIT TIMEOUT 1
ENDDO
This code is in the first button Click method. Form object have user-defined 'cancelpressed' property. In the second button click method I put this:
thisForm.cancelpressed = .T.
Thisform.Release()
Clear Events
But it not work. When loop started it dont want to listen any commands and clicks, and it dont let to close the program. Please help if you can
You could try setting
Application.AutoYield = .T.
as per https://msdn.microsoft.com/en-us/library/aa977324(v=vs.71).aspx
But if that doesn't work then I think you are stuck as VFP is not a true multithreaded application. You might be able to get around the problem using a timer object as per http://fox.wikis.com/wc.dll?Wiki~TimerExample or using a multi threading workaround from https://blogs.msdn.microsoft.com/calvin_hsia/2006/05/16/create-multiple-threads-from-within-your-application/ but you would be very much on your own.
I have to say that starting a new application in VFP today probably isn't the best idea. There are plenty of current alternatives.
The problem is with your wait window. Remove it.
Local greenColor, orangeColor, redColor
m.greenColor = 0x00FF00
m.orangeColor = 0x3060FF
m.redColor = 0xFF0000
Do While !Thisform.cancelpressed
randNum=Val(Trim(Str(Round( 3*Rand(), 1))))
If m.randNum = Val("1")
Thisform.shape1.BackColor = m.greenColor
Thisform.shape2.BackColor = m.orangeColor
Thisform.shape3.BackColor = m.redColor
Endif
Doevents
Enddo
(I don't understand why you are doing such a weird randNum setting and check nor the purpose of setting the same colours again and again but it is not the point in this question)
Normally you should prefer using a Timer with a code like this.
And BTW this has nothing to do with multithreading neither in VFP nor in another language. You are simply doing a loop with a cancel flag check. Updating the UI, say in C#, with the same approach wouldn't be any easier.

AngularJS Microsoft Edge Screen doesn't reflect the DOM

I'm using AngularJS 1.5.0 and Microsoft Edge browser screen doesn't reflect the DOM.
I would like some suggestion how this can be fixed.
I can't really apply a fix for each element as the application is somewhat big with dynamic user content including Angular equations.
Also the app include a lot of dynamic bindings linked to input boxes.
Selecting the text with the mouse turn the 0 into a 2 which is the right value in the example below.
Also changing the position style back and forth seem to force Edge to redraw the element but it's somewhat an ugly fix that I don't like very much and it need to be trigger at so many places (Ajax request, input changes and so on...)
The page start with a value of 0. Then an Ajax call is made and it go fetch the real data. After some experimentation the bug only appears if the new data is 1 character (ex: 2 or 9). And it happens every time. If it's a 2 digit number (ex: 26) then the good number appears.
Any help on this matter would be gladly appreciated.
We were facing the same problem and it stopped occurring after removing the text-transform: uppercase style from the elements that are not updating.
#Sampson, it looks like this is a bug in Edge.
I was able to make a temporary fix with the use of Mutation Observer.
Little script that I made that works for AngularJS elements created server side.
Currently those are the only one causing trouble in my app.
<script>
$(document).ready(function(){
var ua = navigator.userAgent;
var re = new RegExp("Edge/");
if (re.exec(ua) != null){
console.log('edgeMutationObserver ON!!')
var edgeMutationConfig = { characterData: true, subtree: true };
var edgeMutationObserver = new MutationObserver(function(mutations) {
var rgb_p = /rgb\((\d+), (\d+), (\d+)\)/g;
var rgba_p = /rgba\((\d+), (\d+), (\d+), (\d.?\d*)\)/g;
mutations.forEach(function(mutation){
if(mutation.target.nodeType == 3){
var that = mutation.target.parentNode;
// Save the background color
var bgc = that.style.backgroundColor;
// Get applied style from style or css
var bgc_css = bgc || $(that).css('backgroundColor');
var bgc_temp,match;
if(match = rgb_p.exec(bgc_css)){
// rgb transformed in rgba triggers update
bgc_temp = 'rgba('+match[1]+','+match[2]+','+match[3]+',1)';
}else if(match = rgba_p.exec(bgc_css)){
// Slightly modify transparency
var alpha = match[4] == 0 ? 0.01 : match[4] - 0.01 ;
bgc_temp = 'rgba('+match[1]+','+match[2]+','+match[3]+','+alpha+')';
}else{
// If either inline style or css is already equal to transparent the redraw is not made so i choose an alternate color with 0 opacity
bgc_temp = bgc_css != 'transparent' ? 'transparent' : 'rgba(0,0,0,0)';
}
// Change background color to force redraw
that.style.backgroundColor = bgc_temp;
setTimeout(function(){
// Apply back previous style
// Doesn't redraw without a timeout in Edge
that.style.backgroundColor = bgc;
},0);
}
});
});
$('.ng-binding').each(function(){
edgeMutationObserver.observe(this, edgeMutationConfig);
});
}
});
</script>

wxpython SetFocus and EVT_KILL_FOCUS combobox

I am trying to understand how EVT_KILL_FOCUS and SetFocus on a combobox works .Here is the following code:
import wx
class MainWindow(wx.Frame):
count = 1
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(150,150), style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER ^ wx.MAXIMIZE_BOX)
panel = wx.Panel(self, -1)
self.Calc_Display = wx.ComboBox(panel, -1, style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)
self.Calc_Display.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
btn = wx.Button(panel, label="Test")
MainFrameSizer = wx.BoxSizer(wx.VERTICAL)
MainFrameSizer.Add(self.Calc_Display, 0, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 5)
MainFrameSizer.Add(btn, 0, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 5)
panel.SetSizer(MainFrameSizer)
panel.Fit()
self.Show()
def OnKillFocus(self, event):
print ('EVT_KILL_FOCUS was called %i times' %MainWindow.count)
MainWindow.count += 1
# self.Calc_Display.SetFocus()
event.Skip()
app = wx.App(False)
frame = MainWindow(None, "Test")
app.MainLoop()
If run this, you will get a print every time the combobox loses focus, which is expected.
If you uncomment line 28, that's when it gets weird. The EVT_KILL_FOCUS gets called over and over. That is the behavior I am trying to understand. In the program I am writing, I want to force the combobox to maintain focus in case a condition is not satisfied. Are there any ways around this behavior?
I found this link on the issue, but I did not quite understand it: http://wiki.wxpython.org/Surviving%20with%20wxEVT%20KILL%20FOCUS%20under%20Microsoft%20Windows
Thanks for any help
After reading the link posted in your question, and playing around with your code, I came to the conclusion that calling SetFocus() on the combobox is apparently triggering the EVT_KILL_FOCUS in Windows. I had noticed that on running the program, it prints the statement once, although It shouldn't since the combobox is not losing focus.
I tried two things:
First was to move the combo box code after the button code. In this case when the program is run the Focus is on the button, and sure enough the statement is not printed!
Here's the edit:
btn = wx.Button(panel, label="Test")
self.Calc_Display = wx.ComboBox(panel, -1, style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)
self.Calc_Display.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
Second was to try binding the btn to a handler which sets the focus on the combobox
btn.Bind(wx.EVT_BUTTON, self.On_Button)
def On_Button(self, event):
self.Calc_Display.SetFocus()
In this case the statement was being printed twice every time the button was being clicked. I guess this is once for when the focus is lost and once for setting back the focus. Note that the SetFocus() is still commented out in the OnKillFocus in this case.
Back to your code: If the SetFocus is "uncomment-ed" the statement is printed many times because it keeps setting the focus which in turn triggers the event and it goes on in a loop. This may be a wrong explanation, but nevertheless it is the only thing I could think of.

iOS 6: UITextField textAlignment does not change cursor position

I use an instance of UITextField in which the text is normally aligned to the right, but switches to left alignment when being edited. This is done by calling setTextAlignment: on the editingDidBegin event. Since the update to iOS 6 this behaves strangely: The text alignment is changed correctly from right to left, but the cursor remains at the far right of the text field until some input is performed.
Does anybody know how to restore the expected behaviour so that the cursor moves as well when the alignment is changed?
To give some context: I use the text field to show a value with a unit. The unit is removed during editing and then displayed again after the user hits enter.
Method called on event editingDidBegin:
- (IBAction)textEditingDidBegin:(UITextField *)sender
{
[sender setTextAlignment:NSTextAlignmentLeft];
[sender setText:[NSString stringWithFormat:#"%.0f", width]];
}
Method called on event editingDidEnd:
- (IBAction)textEditingDidEnd:(id)sender
{
[sender setTextAlignment:UITextAlignmentRight];
[sender setText:[NSString stringWithFormat:#"%.0f m", width]];
}
Try resigning the textView as first responder, then make it first responder right after that.
textView.textAlignment = NSTextAlignmentCenter;
[textView resignFirstResponder];
[textView becomeFirstResponder];
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
textField.textAlignment = NSTextAlignmentLeft ;
return YES ;
}
Change the textAlignment before editing did begin. The best place I know to do this is in the UITextFieldDelegate method textFieldShouldBeginEditing.

Resources