How do I change the speed of an AnimationTimer in JavaFX? - animation

I'm trying to change the speed of an AnimationTimer so the code runs slower, here is the code I have so far:
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long now) {
if (upOrDown != 1) {
for (int i = 0; i < 4; i++) {
snakePositionDown[i] = snake[i].getX();
snakePositionDownY[i] = snake[i].getY();
}
snake[0].setY(snake[0].getY() + 25);
for (int i = 1; i < 4; i++) {
snake[i].setX(snakePositionDown[i - 1]);
snake[i].setY(snakePositionDownY[i - 1]);
}
leftOrRight = 2;
upOrDown = 0;
}
}
};
timer.start();
How would I make the AnimationTimer run slower?
Thanks in advance!

You could use a Timeline for this purpose. Adjusting the Timeline.rate property also allows you to update the "speed":
// update once every second (as long as rate remains 1)
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), event -> {
if (upOrDown != 1) {
for (int i = 0; i < 4; i++) {
snakePositionDown[i] = snake[i].getX();
snakePositionDownY[i] = snake[i].getY();
}
snake[0].setY(snake[0].getY() + 25);
for (int i = 1; i < 4; i++) {
snake[i].setX(snakePositionDown[i - 1]);
snake[i].setY(snakePositionDownY[i - 1]);
}
leftOrRight = 2;
upOrDown = 0;
}
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
...
// double speed
timeline.setRate(2);

An AnimationTimer's handle() method is invoked on every "pulse" - i.e., every time a frame is rendered. By default, the JavaFX toolkit will attempt to do this 60 times per second, but that is not in any way guaranteed. It can be changed by setting a system property, and it is possible that future versions of JavaFX will attempt to execute pulses more frequently. If the FX Application Thread has a large amount of work to do, then pulses may occur less frequently than the target rate. Consequently, the code in your handle() method needs to account for the amount of time since the last update.
The parameter passed to the handle(...) method represents the current system time in nanoseconds. So a typical way to approach this is:
AnimationTimer h = new AnimationTimer() {
private long lastUpdate; // Last time in which `handle()` was called
private double speed = 50 ; // The snake moves 50 pixels per second
#Override
public void start() {
lastUpdate = System.nanoTime();
super.start();
}
#Override
public void handle(long now) {
long elapsedNanoSeconds = now - lastUpdate;
// 1 second = 1,000,000,000 (1 billion) nanoseconds
double elapsedSeconds = elapsedNanoSeconds / 1_000_000_000.0;
// ...
snake[0].setY(snake[0].getY() + elapsedSeconds * speed);
// ...
lastUpdate = now;
}
}

Related

FCFS inside memory list

Hi i am new in java programing. I've created a program to allocate 20 block inside 10 memory.
Here's the code
import java.util.*;
import java.io.*;
public class BestFit
{
private int[] job;//f
private int[] memBlock;//b
private int[] jobStatus;
private int[] jobAT;
static private int[] memTaken;
static int[] ff;
private int[] jobCC;
private int[] ArrivalTime;
private int[] waitingTime;
private int[] turnaroundTime;
public BestFit()
{
job = new int[]{5040,4600,1060,1950,6950,6410,2960,3070,2770,7790,5680,9150,7880,3870,7160,8880,4410,6130,6750,2560};
memBlock = new int[]{4400,6200,9300,1000,4200,8200,4600,3700,6300,2900};
memTaken = new int[20];
ff = new int[20];//to store no. of block that used by particular file
jobCC = new int[]{2,8,10,1,10,8,4,2,6,7,1,1,1,8,8,2,5,7,6,7};//cpu cycle
ArrivalTime = new int[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
waitingTime = new int[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
turnaroundTime = new int[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
}
public void BestFitAlgo()
{
int[] frag = new int[25];
int i,j,nb,nf,sizeDifference;
int lowest = 10000;
nf = 20;
nb = 10;
int startTime = 1;
int complete = 1;
int totalTime = 1;
int waitTime;
int tTime = 1;
Arrays.sort(memBlock);
for (i=0;i<nf;i++)
{
if (complete != 20)
{
for (j=0;j<nb;j++)
{
sizeDifference = memBlock[j] - job[i];
if (sizeDifference>=0)
if (lowest>sizeDifference)
{
ff[i] = j;//no of block = j
lowest = sizeDifference;
complete++;
System.out.println("Job: "+i+" is added to block: "+ff[i]+" and being process");
for (int k = 1;k<jobCC[i];k++)
{
startTime++;
}
if(startTime == jobCC[i])
{
waitingTime[i] = tTime - ArrivalTime[i];
turnaroundTime[i] = jobCC[i] + waitingTime[i];
System.out.println("Job: "+i+" is fully processed.Block: "+ff[i]+" is free");
System.out.println("Arrival Time: "+ArrivalTime[i]);
System.out.println("Start time: "+totalTime);
System.out.println("CPU cycle: "+jobCC[i]);
totalTime +=startTime;
startTime = 1;
tTime = totalTime;
System.out.println("Waiting time: "+waitingTime[i]);
System.out.println("Turnaround time: "+turnaroundTime[i]+"\n");
}
}
}
}
frag[i]=lowest;
lowest = 10000;
}
System.out.println("File No:\tFile_Size:\tBlock_No:\tBlock_Size:\tFragment");
for (i=0;i<nf&&ff[i]!=0;i++)
{
System.out.println(i+"\t\t"+job[i]+"\t\t"+ff[i]+"\t\t"+memBlock[ff[i]]+"\t\t"+frag[i]);
}
System.out.println("\nTotal time: "+totalTime);
}
public static void main (String[] args)
{
BestFit b = new BestFit();
b.BestFitAlgo();
}
}
For now the job can be allocated to the memory block by fcfs but the problem now is the next job wont be able to enter the memory list ( where all the block) until the previous job is done. So there are 9 free memory block everytime a job enter.
How do i make it so that job can enter the block simultaneously (with the condition the desired mem block is not occupied and based on arrival time).
I know how fcfs work but that is with only 1 memory block. I've been googling all day trying to find how fcfs work in multiple memory block but no avail.
I hope anyone can help me to understand how it work and maybe a hint on how to implement in in coding.
Thanks in advance
EDIT: i put my code instead so anyone can get a clear view of my problem.

How to spawn objects at random times?

I am trying to create a script that will spawn objects at random times, and unfortunately mine isn't working very well. Can you please help me in randomizing the time between the spawns of the Game Objects? Thanks!
#pragma strict
var SpawnObject : GameObject;
var SpawnPoint : GameObject;
var SpawnCounter : int = 0;
var SpawnCounterMinMax : int =0;
var SpawnCounterMaxMax : int =0;
function Update ()
{
var float_min_bother_I_hate_you_js : float = this.SpawnCounterMinMax;
var float_max_bother_I_hate_you_js : float = this.SpawnCounterMaxMax;
var SpawnCounterMax = Random.Range(float_min_bother_I_hate_you_js, float_max_bother_I_hate_you_js);
this.SpawnCounter++;
if (this.SpawnCounter >= SpawnCounterMax )
{
Instantiate(this.SpawnObject, this.SpawnPoint.transform.position, this.SpawnPoint.transform.rotation );
this.SpawnCounter = 0;
SpawnCounterMax = Random.Range(float_min_bother_I_hate_you_js, float_max_bother_I_hate_you_js);
}
}
If you want to be able to specify a min/max random timeframe something like this should work:
#pragma strict
var SpawnObject : GameObject;
var SpawnPoint : GameObject;
var NextSpawnTime : float = 0;
var MinSpawnTime : float =0;
var MaxSpawnTime : float =0;
function SetTimer()
{
this.NextSpawnTime = Random.Range(this.MinSpawnTime, this.MaxSpawnTime);
}
function Start ()
{
//initialise the spawn counter at startup
this.SetTimer();
}
function Update ()
{
this.NextSpawnTime -= Time.deltaTime;
if(this.NextSpawnTime <= 0)
{
Instantiate(this.SpawnObject, this.SpawnPoint.transform.position, this.SpawnPoint.transform.rotation );
this.SetTimer();
}
}
Using Time.deltaTime to decrement a timer that stores some value in seconds ensures that your spawns happen in the given range regardless of framerate.
To further clarify why you might be seeing unwanted behaviour in your code. You are re-randomising the max value for SpawnCounter each update, rather than setting it once each time an object is spawned.
You could use a coroutine to achieve this, something like this would do.
int numberOfObjectsToCreate = 5; // number of objects you want to spawn.
float minTimeDiff = 1.0f; // minimum time difference between 2 objects spawned.
float maxTimeDiff = 5.0f; // Maximam time difference between 2 spawns.
public GameObject ObjectToSpawn; // object that is to be spawned;
void Start() {
StartCoroutine(CreateObjectsAtRandom());
}
IEnumerator CreateObjectsAtRandom() {
for(int i = 0; i < numberOfObjectsToCreate; i++) {
GameObject obj = Instantiate(ObjectToSpawn, Vector3.zero, Quarternion.identity) as GameObject;
yield return new WaitForSeconds(Random.Range(minTimeDiff, maxTimeDiff)); // wait for a random time before spawning the next object.
}
}

How to run processing script on multiple frames in a folder

Using processing I am trying to run a script that will process a folder full of frames.
The script is a combination of PixelSortFrames and SortThroughSeamCarving.
I am new to processing and what I want does not seems to be working. I would like the script to run back through and choose the following file in the folder to be processed. At the moment it stops at the end and does not return to start on next file (there are three other modules also involved).
Any help would be much appreciated. :(
/* ASDFPixelSort for video frames v1.0
Original ASDFPixelSort by Kim Asendorf <http://kimasendorf.com>
https://github.com/kimasendorf/ASDFPixelSort
Fork by dx <http://dequis.org> and chinatsu <http://360nosco.pe>
// Main configuration
String basedir = ".../Images/Seq_002"; // Specify the directory in which the frames are located. Use forward slashes.
String fileext = ".jpg"; // Change to the format your images are in.
int resumeprocess = 0; // If you wish to resume a previously stopped process, change this value.
boolean reverseIt = true;
boolean saveIt = true;
int mode = 2; // MODE: 0 = black, 1 = bright, 2 = white
int blackValue = -10000000;
int brightnessValue = -1;
int whiteValue = -6000000;
// -------
PImage img, original;
float[][] sums;
int bottomIndex = 0;
String[] filenames;
int row = 0;
int column = 0;
int i = 0;
java.io.File folder = new java.io.File(dataPath(basedir));
java.io.FilenameFilter extfilter = new java.io.FilenameFilter() {
boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(fileext);
}
};
void setup() {
if (resumeprocess > 0) {i = resumeprocess - 1;frameCount = i;}
size(1504, 1000); // Resolution of the frames. It's likely there's a better way of doing this..
filenames = folder.list(extfilter);
size(1504, 1000);
println(" " + width + " x " + height + " px");
println("Creating buffer images...");
PImage hImg = createImage(1504, 1000, RGB);
PImage vImg = createImage(1504, 1000, RGB);
// draw image and convert to grayscale
if (i +1 > filenames.length) {println("Uh.. Done!"); System.exit(0);}
img = loadImage(basedir+"/"+filenames[i]);
original = loadImage(basedir+"/"+filenames[i]);
image(img, 0, 0);
filter(GRAY);
img.loadPixels(); // updatePixels is in the 'runKernals'
// run kernels to create "energy map"
println("Running kernals on image...");
runKernels(hImg, vImg);
image(img, 0, 0);
// sum pathways through the image
println("Getting sums through image...");
sums = getSumsThroughImage();
image(img, 0, 0);
loadPixels();
// get start point (smallest value) - this is used to find the
// best seam (starting at the lowest energy)
bottomIndex = width/2;
// bottomIndex = findStartPoint(sums, 50);
println("Bottom index: " + bottomIndex);
// find the pathway with the lowest information
int[] path = new int[height];
path = findPath(bottomIndex, sums, path);
for (int bi=0; bi<width; bi++) {
// get the pixels of the path from the original image
original.loadPixels();
color[] c = new color[path.length]; // create array of the seam's color values
for (int i=0; i<c.length; i++) {
try {
c[i] = original.pixels[i*width + path[i] + bi]; // set color array to values from original image
}
catch (Exception e) {
// when we run out of pixels, just ignore
}
}
println(" " + bi);
c = sort(c); // sort (use better algorithm later)
if (reverseIt) {
c = reverse(c);
}
for (int i=0; i<c.length; i++) {
try {
original.pixels[i*width + path[i] + bi] = c[i]; // reverse! set the pixels of the original from sorted array
}
catch (Exception e) {
// when we run out of pixels, just ignore
}
}
original.updatePixels();
}
// when done, update pixels to display
updatePixels();
// display the result!
image(original, 0, 0);
if (saveIt) {
println("Saving file...");
//filenames = stripFileExtension(filenames);
save("results/SeamSort_" + filenames + ".tiff");
}
println("DONE!");
}
// strip file extension for saving and renaming
String stripFileExtension(String s) {
s = s.substring(s.lastIndexOf('/')+1, s.length());
s = s.substring(s.lastIndexOf('\\')+1, s.length());
s = s.substring(0, s.lastIndexOf('.'));
return s;
}
This code works by processing all images in the selected folder
String basedir = "D:/things/pixelsortframes"; // Specify the directory in which the frames are located. Use forward slashes.
String fileext = ".png"; // Change to the format your images are in.
int resumeprocess = 0; // If you wish to resume a previously stopped process, change this value.
int mode = 1; // MODE: 0 = black, 1 = bright, 2 = white
int blackValue = -10000000;
int brightnessValue = -1;
int whiteValue = -6000000;
PImage img;
String[] filenames;
int row = 0;
int column = 0;
int i = 0;
java.io.File folder = new java.io.File(dataPath(basedir));
java.io.FilenameFilter extfilter = new java.io.FilenameFilter() {
boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(fileext);
}
};
void setup() {
if (resumeprocess > 0) {i = resumeprocess - 1;frameCount = i;}
size(1920, 1080); // Resolution of the frames. It's likely there's a better way of doing this..
filenames = folder.list(extfilter);
}
void draw() {
if (i +1 > filenames.length) {println("Uh.. Done!"); System.exit(0);}
row = 0;
column = 0;
img = loadImage(basedir+"/"+filenames[i]);
image(img,0,0);
while(column < width-1) {
img.loadPixels();
sortColumn();
column++;
img.updatePixels();
}
while(row < height-1) {
img.loadPixels();
sortRow();
row++;
img.updatePixels();
}
image(img,0,0);
saveFrame(basedir+"/out/"+filenames[i]);
println("Frames processed: "+frameCount+"/"+filenames.length);
i++;
}
essentially I want to do the same thing only with a different image process but my code is not doing this to all with in the folder... just one file.
You seem to be confused about what the setup() function does. It runs once, and only once, at the beginning of your code's execution. You don't have any looping structure for processing the other files, so it's no wonder that it only processes the first one. Perhaps wrap the entire thing in a for loop? It looks like you kind of thought about this, judging by the global variable i, but you never increment it to go to the next image and you overwrite its value in several for loops later anyway.

Loading in a movie clip after score reaches certain amount

I have almost finished my project, however when I try to load in a movie clip in my library when the score I have reaches 100, it removes the game from the stage, but doesn't show the screen that I am trying to show.
The code I have written is below. Any assistance would be greatly appreciated.
package
{
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.Timer;
import flash.utils.getDefinitionByName;
public class blast_game extends MovieClip
{
// creates a variable that stores the catcher that
//will be used to collect the chocolate bars.
var catcher:Catcher;
var nextObject:Timer;
var objects:Array = new Array();
var score:int = 0;
const speed:Number = 7.0;
//end of catcher code
//beginning of game code - spawns a new catcher on screen
//at start of game.
public function blast_game()
{
catcher = new Catcher();
catcher.y = 350;
addChild(catcher);
setNextObject();
addEventListener(Event.ENTER_FRAME, moveObjects);
}
//end of catcher spawn
//sets variables for the random object drops,
//increments the objects to appear every second.
public function setNextObject()
{
nextObject = new Timer(1000+Math.random()*1000,1);
nextObject.addEventListener(TimerEvent.TIMER_COMPLETE,newObject);
nextObject.start();
}
//end of object variables
public function newObject(e:Event)
{
//creates an array to hold the "Good" and "Bad" objects in
//the application.
var goodObjects:Array = ["Circle1","Circle2"];
var badObjects:Array = ["Square1","Square2"];
if (Math.random() < .5)
{
//replaces the "good" object when the object hits the floor, places
//object back in array to drop again.
var r:int = Math.floor(Math.random() * goodObjects.length);
var classRef:Class = getDefinitionByName(goodObjects[r]) as Class;
var newObject:MovieClip = new classRef();
newObject.typestr = "good";
//end of "Good" object replacement
}
else
{
//replaces the "Bad" object when the object hits the floor, places
//object back in array to drop again
r = Math.floor(Math.random() * badObjects.length);
classRef = getDefinitionByName(badObjects[r]) as Class;
newObject = new classRef();
newObject.typestr = "bad";
//end of "Bad" object replacement
}
//randomises the location the objects will be placed on stage
//after replacement.
newObject.x = Math.random() * 500;
addChild(newObject);
objects.push(newObject);
setNextObject();
//end of object randomisation
}
public function moveObjects(e:Event)
{
for (var i:int=objects.length-1; i>=0; i--)
{
//code to increase speed of objects over time.
objects[i].y += speed;
if (objects[i].y > 400)
{
removeChild(objects[i]);
objects.splice(i,1);
}
//hit test for catcher - if any object hits the catcher
//increase or decrease score respectively.
if (objects[i].hitTestObject(catcher))
{
//increase score when catcher catches "Good" object
if (objects[i].typestr == "good")
{
score += 10;
}
else
//decrease score if catcher catches "Bad" object.
{
score -= 5;
}
//prevents score from going below 0
if (score < 0)
{
score = 0;
}
scoreDisplay.text = "Score: " + score;
//once object hits catcher, remove object from stage.
removeChild(objects[i]);
objects.splice(i,1);
}
//if statement to move screen to promotion screen
//once score reaches past 100
//THIS IS WHERE I THINK THE ISSUE IS!!!
if(score >= 100) {
var promotionScreen:promotion = new promotion;
//stage.removeChild(this)
addChild(promotionScreen);
removeEventListener(Event.ENTER_FRAME, moveObjects);
promotionScreen = stage.stageWidth / 2;
promotionScreen = stage.stageHeight /2;
}
//end of if statement
}
//sets catcher to work with mouse movement.
catcher.x = mouseX;
}
}
}
You should set break inside, at the end of if(score >= 100) because this condition can be launched a couple of times in your for loop. Also your MovieClip can be stopped, so try .play() or .gotoAndStop()
Oh! and you set promotionScreen = stage.stageWidth/2 while you should promotionScreen.x = stage.stageWidth/2

Windows phone 8 gps / altitude problems

UPDATE: using the sample from here - http://code.msdn.microsoft.com/wpapps/Location-sample-f11aa4e7 and adding an altitude readout I get the same thing as my code. Poor accuracy is being off by 50ft. Going back and forth between 720 (correct) and 300 ft means something is wrong. I just can't see where...
I'm starting to make a GPS tracking app for windows phone 8 but something is going haywire. In my app, (and in the sample location app) i get some readings that are correct and others that are not. In general, the altitude jumps back and forth between ~95 and ~215 (with 215 being correct). The distance I'm getting is hugely inaccurate as well, quickly jumping to several miles while sitting at my desk or walking around outside.
I'm not sure what code to post, as it is identical to the sample code. If you think there is another relevant section i should post let me know and I'll add it.
double maxSpeed = 0.0;
double maxAlt = -9999999.0;
double minAlt = 9999999.0;
double curDistance = 0.0;
GeoCoordinate lastCoord = null;
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if ((bool)IsolatedStorageSettings.ApplicationSettings["LocationConsent"] != true)
{
// The user has opted out of Location.
return;
}
if (App.Geolocator == null)
{
// Use the app's global Geolocator variable
App.Geolocator = new Geolocator();
}
App.Geolocator.DesiredAccuracy = PositionAccuracy.High;
//App.Geolocator.MovementThreshold = 1; // The units are meters.
App.Geolocator.ReportInterval = 1000;
//App.Geolocator.DesiredAccuracyInMeters = 50;
App.Geolocator.StatusChanged += geolocator_StatusChanged;
App.Geolocator.PositionChanged += geolocator_PositionChanged;
/*
geolocator = new Geolocator();
geolocator.DesiredAccuracy = PositionAccuracy.High;
//geolocator.MovementThreshold = 1; // The units are meters.
geolocator.ReportInterval = 1000;
geolocator.StatusChanged += geolocator_StatusChanged;
geolocator.PositionChanged += geolocator_PositionChanged;
*
* */
logging = true;
startTime = DateTime.Now;
}
public static GeoCoordinate ConvertGeocoordinate(Geocoordinate geocoordinate)
{
return new GeoCoordinate
(
geocoordinate.Latitude,
geocoordinate.Longitude,
geocoordinate.Altitude ?? Double.NaN,
geocoordinate.Accuracy,
geocoordinate.AltitudeAccuracy ?? Double.NaN,
geocoordinate.Speed ?? Double.NaN,
geocoordinate.Heading ?? Double.NaN
);
}
void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
Dispatcher.BeginInvoke(() =>
{
if (lastCoord == null)
{
lastCoord = ConvertGeocoordinate(args.Position.Coordinate);
}
DateTime currentTime = DateTime.Now;
TimeSpan totalTime = currentTime - startTime;
timeValue.Text = totalTime.ToString(#"hh\:mm\:ss");
System.Diagnostics.Debug.WriteLine(args.Position.Coordinate.Altitude.ToString());
GeoCoordinate thisLocation = ConvertGeocoordinate(args.Position.Coordinate);
if (true) //units check true = standard
{
double speed = (double)thisLocation.Speed;
speed *= 2.23694; //m/s -> mph
speedValue.Text = speed.ToString("0");
double alt = (double)thisLocation.Altitude;
if (alt > maxAlt)
{
maxAlt = alt;
}
if (alt < minAlt)
{
minAlt = alt;
}
/*
double currentAlt = (maxAlt - minAlt);
currentAlt *= 3.28084; //m -> ft
* */
alt *= 3.28084;
altValue.Text = alt.ToString("0");
double distance = thisLocation.GetDistanceTo(lastCoord);
curDistance += distance;
distance = curDistance * 0.000621371; // m -> miles
distanceValue.Text = distance.ToString("0.00");
distanceUnits.Text = "(mi)";
speedUnits.Text = "(mph)";
altUnits.Text = "(ft)";
}
});
}
EDIT: I didn't mention, but the speed is perfectly fine as an fyi. the lat / long is pretty close in general to where i am as well, so I don't think it's a hardware issue.
UPDATE: When stopping in the debugger to check the value instead of just printing it, it gives this:
Altitude = An internal error has occurred while evaluating method Windows.Devices.Geolocation.Geocoordinate.get_Altitude()
I tried to search for this, but the error is nowhere to be found on the internet...
The documentation states that altitude and a few others aren't guaranteed, but it also says that the value will be null if it isn't there. I check, and it's never null. It always prints a value, either correct or ~400 ft off.
UPDATE: Sample code:
void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
System.Diagnostics.Debug.WriteLine(args.Position.Coordinate.Altitude.ToString());
if (!App.RunningInBackground)
{
Dispatcher.BeginInvoke(() =>
{
LatitudeTextBlock.Text = args.Position.Coordinate.Latitude.ToString("0.00");
LongitudeTextBlock.Text = args.Position.Coordinate.Longitude.ToString("0.00");
});
}
else
{
Microsoft.Phone.Shell.ShellToast toast = new Microsoft.Phone.Shell.ShellToast();
toast.Content = args.Position.Coordinate.Latitude.ToString("0.00");
toast.Title = "Location: ";
toast.NavigationUri = new Uri("/MainPage.xaml", UriKind.Relative);
toast.Show();
}
}
You might be seeing a different issues (too) but GPS altitudes are not very reliable. I have a few Garmin devices and they all jump about all over the place. You really need a barometer for decent altitude accuracy.
Here is a link on GPS attitude inaccuracy GPS Elevation

Resources