I'm building a basic kids app for iOS and I want to fade-in and fade-out my background to sync with my sun and moon animation.
The problem is, my fade-in and fade-out code, has a lower value of 0.01 and still too fast for my app, I want a slow fade animation, like 0.001 but it's not working with this values.
bgLight.addEventListener(Event.ENTER_FRAME, fadeout);
function fadeout(e:Event){
if(bgLight.alpha <=0){
bgLight.removeEventListener(Event.ENTER_FRAME, fadeout);
bgLight.addEventListener(Event.ENTER_FRAME, fadein);
} else {
bgLight.alpha -=.01; // That's the small value
}
}
function fadein(e:Event){
if(bgLight.alpha >= 1){
bgLight.removeEventListener(Event.ENTER_FRAME, fadein);
bgLight.addEventListener(Event.ENTER_FRAME, fadeout);
} else {
bgLight.alpha +=.01; // That's the small value
}
}
Is it possible the reach a small value like 0.001 using ENTER_FRAME?
My project has 60 FPS.
Yeah, actually I'm using now the Greensock engine for this basic tween.
It's very easy to use, and I think will use less CPU usage.
import com.greensock.*;
import com.greensock.easing.*;
TweenMax.to(bgLight, 35.5, {alpha:0, repeatDelay:1, repeat:-1, yoyo:true});
Thanks for your time guys.
Related
I'm throwing a lot of objects across the screen (1 beachball every 0.1s) and swiping them toward a box, the balls are recycled after they leave the screen or hit the ball. The problem i encountered is that when multiple balls hit the box, frame rates drop drastically. I'm not sure what's making this happen. Is there a better way to do the following so that it doesn't lag? I use the default cocos library to play sounds.
-(void)ccPhysicsCollisionPostSolve:(CCPhysicsCollisionPair *)pair can:(CCNode *)nodeA wildcard:(CCNode *)nodeB {
if([nodeB.physicsBody.collisionType isEqualToString:#"hit"]){
[[_physicsNode space] addPostStepBlock:^{
[self remove:nodeA];
} key:nodeB];
}else if([nodeB.physicsBody.collisionType isEqualToString:#"floor"]){
[[_physicsNode space] addPostStepBlock:^{
[self remove:nodeA];
} key:nodeB];
}else {
[self playSound:#"collide.mp3" bg:YES];
}
}
I am creating a very simple game using Swift and SpriteKit and I am moving a ball on the screen using the accelerometer data (acceleration x,y).
I would say the code works fine but I have noticed that sometimes (often right when I open the app) the accelerometer data is not correct and delayed for few seconds.
Why is that happening?
I am using the following code to read the accelerometer data:
if motionManager.accelerometerAvailable == true {
motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.currentQueue(), withHandler:{
data, error in
self.accX = CGFloat(data.acceleration.x)
self.accY = CGFloat(data.acceleration.y)
})
}
And the function update to apply some impulse to the ball:
override func update(currentTime: CFTimeInterval) {
var impulse = CGVectorMake(accX, accY)
var obj = childNodeWithName("ball") as SKSpriteNode
obj.physicsBody?.applyImpulse(impulse)
}
Am i missing something?
Thank you
With any accelerometer data, it is a good idea to run it through a filter to smooth out any irregular spikes. Here is my favorite:
double filteredAcceleration[3];
memset(filteredAcceleration, 0, sizeof(filteredAcceleration));
CMAccelerometerData *newestAccel = motionManager.accelerometerData;
filteredAcceleration[0] = (filteredAcceleration[0]*(1.0-alpha)) + (newestAccel.acceleration.x*alpha);
filteredAcceleration[1] = (filteredAcceleration[1]*(1.0-alpha)) + (newestAccel.acceleration.y*alpha);
filteredAcceleration[2] = (filteredAcceleration[2]*(1.0-alpha)) + (newestAccel.acceleration.z*alpha);
alpha can be any value from 0 to 1. The closer to 1 the more responsive it will be, the closer to zero the more smooth it will be. My favorite value on the iPhone is 0.2 It is a good compromise for smooth yet responsive for a game like doodle jump, or possibly moving a ball around.
I don't know why the accelerometer data is incorrect/delayed on startup, my guess would be that the hardware has to wake up and calibrate itself, but regardless of the why, if you implement a filter, it will smooth out these irregularities, and they won't be nearly as noticeable.
I have given priority to both functions and the issue seems fixed.
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
// do some task
dispatch_async(dispatch_get_main_queue()) {
// code with priority
}
}
I am working on an app that exposes manual controls for the camera with the new APIs introduced in iOS 8, and I am using this sample app from WWDC 2014 as a reference.
However I noticed a strange bahaviour (on my 5s and on a 6): after setting the exposure mode to "custom" and then back to "auto" the image continues to lag as if the exposure duration was not affected by this change.
Here is the code involved in each step (from the sample app, without any modification):
- (IBAction)changeExposureMode:(id)sender
{
UISegmentedControl *control = sender;
NSError *error = nil;
AVCaptureExposureMode mode = (AVCaptureExposureMode)[self.exposureModes[control.selectedSegmentIndex] intValue];
if ([self.videoDevice lockForConfiguration:&error])
{
if ([self.videoDevice isExposureModeSupported:mode])
{
[self.videoDevice setExposureMode:mode];
}
else
{
NSLog(#"Exposure mode %# is not supported. Exposure mode is %#.", [self stringFromExposureMode:mode], [self stringFromExposureMode:self.videoDevice.exposureMode]);
}
}
else
{
NSLog(#"%#", error);
}
}
- (IBAction)changeExposureDuration:(id)sender
{
UISlider *control = sender;
NSError *error = nil;
double p = pow( control.value, EXPOSURE_DURATION_POWER ); // Apply power function to expand slider's low-end range
double minDurationSeconds = MAX(CMTimeGetSeconds(self.videoDevice.activeFormat.minExposureDuration), EXPOSURE_MINIMUM_DURATION);
double maxDurationSeconds = CMTimeGetSeconds(self.videoDevice.activeFormat.maxExposureDuration);
double newDurationSeconds = p * ( maxDurationSeconds - minDurationSeconds ) + minDurationSeconds; // Scale from 0-1 slider range to actual duration
if (self.videoDevice.exposureMode == AVCaptureExposureModeCustom)
{
if ( newDurationSeconds < 1 )
{
int digits = MAX( 0, 2 + floor( log10( newDurationSeconds ) ) );
self.exposureDurationValueLabel.text = [NSString stringWithFormat:#"1/%.*f", digits, 1/newDurationSeconds];
}
else
{
self.exposureDurationValueLabel.text = [NSString stringWithFormat:#"%.2f", newDurationSeconds];
}
}
if ([self.videoDevice lockForConfiguration:&error])
{
[self.videoDevice setExposureModeCustomWithDuration:CMTimeMakeWithSeconds(newDurationSeconds, 1000*1000*1000) ISO:AVCaptureISOCurrent completionHandler:nil];
}
else
{
NSLog(#"%#", error);
}
}
I noticed this too. It seems to be related to slow shutter speeds. Try this: Go to custom. Set a fast shutter speed. Then go back to Auto. Boom, you're right there. Now, go to custom, set a slow shutter speed (slider to the right). Go back to auto and you can watch the shutter speed gradually move back to a reasonable setting.
This is the case in the sample code and in the app that I wrote based on the sample code. It is also the same for my 4s and 5s.
I believe that this is because the sensor needs to catch a certain number of images in order to pick the right auto setting. With a very slow shutter speed (up to 1 second long max) this means it could take several seconds to find the right setting. Sort of makes sense, even if not what we'd like. Fortunately for me my app never needs a shutter speed more than quarter of second, if that.
I have found in my own code that the setExposureModeCustomWithDuration method has some issue. Though it has a completion handler which is supposed to be called AFTER the duration and ISO are set in the device, it doesn't always work.
There are times, for instance when switching from Auto expose to manual exposure, that if you grab a still from within setExposureModeCustomWithDuration's completion handler, the still is taken with an auto expose setting. If you take another still imedeately after that, it has the correct manual exposure set on it.
I found that a 1 second delay at the beginning of the completion handler works around this issue, but that can't be a proper solution.
I have also tried placing a wait/sleep loop at the beginning of the completion handler where it waits until the device is not adjusting exposure -- that does not help.
I tried the same sample app and tried to reproduce the issue but was not able to it looks like they have fixed it now.
I'm creating an app for iOS (mainly) in Flash CS6 and I'm having a few problems with getting a particular page to work.
The layout is as follows: I have a movie clip that is 3 times the width of the stage with my content, with the instance name of txtContent.
On a separate layer, my Action Script (v3.0) reads as follows:
import com.greensock.*;
import flash.events.MouseEvent;
//Swipe
Multitouch.inputMode = MultitouchInputMode.GESTURE;
var currentTile:Number = 1;
var totalTiles:Number = 3;
txtContent.addEventListener(TransformGestureEvent.GESTURE_SWIPE , onSwipe);
function moveLeft():void{
txtContent.x += 640;
}
function moveRight():void{
txtContent.x -= 640;
}
function onSwipe (e:TransformGestureEvent):void{
if (e.offsetX == 1) {
if(currentTile > 1){
moveLeft()
currentTile--
} else {}
}
if (e.offsetX == -1) {
if(currentTile < totalTiles){
moveRight()
currentTile++
}
}
}
stop();
When I test the movie, with a touch layer, the movie clip successfully moves left and right for each swipe, and does not continue to move too far in either direction, in effect ignoring any other swipes.
However, when I compile the IPA and test on the iPhone, only the first two "tiles" move (I can only see two thirds of the movie clip with swiping), as if I swipe to the third "tile" I cannot swipe back at all. No matter what I do, it gets stuck on that third section.
Is there a problem in my code that isn't registering properly in iOS?
FYI, I'm testing on an iPhone 3GS.
It was my own mistake - the final 'page' of the slides did not have a large background with the alpha set to 0% like the others, therefore to slide it back it would only work when holding the text (which was small). With the addition of the background, the movieclip is solid and therefore swiping the whole screen worked fine.
I have a manometer, this needs to spin from a minimum value to a maximum. right now I have the manometer as a picture and the arrow as a movieclip. I've got it spinning at the right speed, but don't know how to stop it at the lowest/highest pressure.
It's suppose to work like this:
I have two movieclip/buttons; one for simulating more pressure, and one for less.
when the user presses the "more pressure" movieclip/button the pressure begins to rise and the arrow inside the manometer begin to turn.
At the same time as the pressure rises, another movieclip ("stamp") will push uppwards.
then another movieclip/button, "less pressure" simulates pressure drop; when pressed, the same point as the arrow stopped at when pressure rised, will start sinking towards minimum, and the stamp will go down again.
so, when the user presses "more pressure" pressure rises towards maximum, and as soon as the user stop pressing the button, the animation stops (both the stamp and the arrow). And if the user presses "lower pressure", the arrow starts sinking from where it stopped.
heres my code so far: pil1 = manometerarrow, the stamp = stamp, and "less pressure"/"more pressure" = Lpress / mpress
addEventListener (Event.ENTER_FRAME, rotate);
function rotate(event:Event):void
{
pil1.rotation = pil1.rotation+1;
}
ymutlu is on the right track. The mouse down event will only execute once when the mouse is depressed. To make the object rotate continuously while the mouse is depressed you need to increment or decrement the rotation of the object on each frame. I think the following should do the trick:
import flash.events.MouseEvent;
import flash.events.Event;
var rotate = 0;
Hpress.addEventListener(MouseEvent.MOUSE_DOWN, Hpressed);
Hpress.addEventListener(MouseEvent.MOUSE_UP, removeEnterFrame);
Lpress.addEventListener(MouseEvent.MOUSE_DOWN, Lpressed);
Lpress.addEventListener(MouseEvent.MOUSE_UP, removeEnterFrame);
function Hpressed(e:MouseEvent):void
{
rotate = 1;
addEnterFrame();
}
function Lpressed(e:MouseEvent):void
{
rotate = -1;
addEnterFrame();
}
function addEnterFrame():void
{
this.addEventListener(Event.ENTER_FRAME, update);
}
function removeEnterFrame(e:MouseEvent):void
{
this.removeEventListener(Event.ENTER_FRAME, update);
}
function update(e:Event):void
{
pil1.rotation += rotate;
}
hold to varaible that states if max button down or min button down, and check it in enterframe loop. Edited answer on your comment, hope you can sort it out.
addEventListener (Event.ENTER_FRAME, rotate);
function rotate(event:Event):void
{
if(isMaxDown) // true when max button down
pil1.rotation = Math.min(presMax,pil1.rotation+1); // presMax is max value that pressure can go
if(isMinDown) // true when min button down
pil1.rotation = Math.max(presMin,pil1.rotation-1);// presMin is min value that pressure can go
}
// isMaxDown and isMinDown are global values.
Hpress.addEventListener(MouseEvent.MOUSE_DOWN, Hpressed);
Lpress.addEventListener(MouseEvent.MOUSE_DOWN, Lpressed);
Hpress.addEventListener(MouseEvent.MOUSE_UP, H_up);
Lpress.addEventListener(MouseEvent.MOUSE_UP, L_up);
function H_up(e:MouseEvent):void {
isMaxDown=false;
}
function L_up(e:MouseEvent):void {
isMinDown=false;
}
function Hpressed(e:MouseEvent):void {
isMaxDown=true;
}
function Lpressed(e:MouseEvent):void {
isMinDown=true;
}
This code would help you but prob this is not a path to fallow to do somthing like that.