Recognize Namaz time in Specific country - algorithm

I would create free app for muslims which will notify pray time ( namaz time).
I dont know quite a few how to measure pray time (Namaz time).
I saw some example code, but these codes were wrong for My Country (UZBEKISTAN ).
Please, show or explain how to measure Namaz time for Uzbekistan or any country depending on geolocation.

import 'dart:collection';
import 'dart:math' as math;
import 'dart:core';
void main() {
double latitude = 41.311081;
double longitude = 69.240562;
double timezone = 5;
// Test Prayer times here
// PrayTime prayers = new PrayTime();
PrayerTime prayers = new PrayerTime();
prayers.setTimeFormat(prayers.getTime24());
prayers.setCalcMethod(prayers.getISNA());
prayers.setAsrJuristic(prayers.getHanafi());
prayers.setAdjustHighLats(prayers.getAdjustHighLats());
List<int>offsets = [0, 0, 0, 0, 0, 0, 0]; // {Fajr,Sunrise,Dhuhr,Asr,Sunset,Maghrib,Isha}
prayers.tune(offsets);
List<String> prayerTimes = prayers.getPrayerTimes(DateTime.now(),
latitude, longitude, timezone);
List<String> prayerNames = prayers.getTimeNames();
for (int i = 0; i < prayerTimes.length; i++) {
print(prayerNames[i] + " - " + prayerTimes[i]);
}
}
class PrayerTime {
// ---------------------- Global Variables --------------------
int _calcMethod; // caculation method
int _asrJuristic; // Juristic method for Asr
int _dhuhrMinutes; // minutes after mid-day for Dhuhr
int _adjustHighLats; // adjusting method for higher latitudes
int _timeFormat; // time format
double _lat; // latitude
double _lng; // longitude
double _timeZone; // time-zone
double _jDate; // Julian date
// ------------------------------------------------------------
// Calculation Methods
int _jafri; // Ithna Ashari
int _karachi; // University of Islamic Sciences, Karachi
int _iSNA; // Islamic Society of North America (ISNA)
int _mWL; // Muslim World League (MWL)
int _makkah; // Umm al-Qura, Makkah
int _egypt; // Egyptian General Authority of Survey
int _custom; // Custom Setting
int _tehran; // Institute of Geophysics, University of Tehran
// Juristic Methods
int _shaffi; // Shafii (standard)
int _hanafi; // Hanafi
// Adjusting Methods for Higher Latitudes
int _none; // No adjustment
int _midNight; // middle of night
int _oneSeventh; // 1/7th of night
int _angleBased; // angle/60th of night
// Time Formats
int _time24; // 24-hour format
int _time12; // 12-hour format
int _time12Ns; // 12-hour format with no suffix
int _floating; // floating point number
// Time Names
List<String> _timeNames;
String _invalidTime; // The string used for invalid times
// --------------------- Technical Settings --------------------
int _numIterations;
// ------------------- Calc Method Parameters --------------------
Map<int, List<double>> _methodParams;
/*
* this.methodParams[methodNum] = new Array(fa, ms, mv, is, iv);
*
* fa : fajr angle ms : maghrib selector (0 = angle; 1 = minutes after
* sunset) mv : maghrib parameter value (in angle or minutes) is : isha
* selector (0 = angle; 1 = minutes after maghrib) iv : isha parameter value
* (in angle or minutes)
*/
List<double> _prayerTimesCurrent;
List<int> _offsets;
PrayerTime() {
this.setCalcMethod(0);
this.setAsrJuristic(0);
this.setDhuhrMinutes(0);
this.setAdjustHighLats(1);
this.setTimeFormat(0);
// Calculation Methods
this.setJafari(0); // Ithna Ashari
this.setKarachi(1); // University of Islamic Sciences, Karachi
this.setISNA(2); // Islamic Society of North America (ISNA)
this.setMWL(3); // Muslim World League (MWL)
this.setMakkah(4); // Umm al-Qura, Makkah
this.setEgypt(5); // Egyptian General Authority of Survey
this.setTehran(6); // Institute of Geophysics, University of Tehran
this.setCustom(7); // Custom Setting
// Juristic Methods
this.setShafii(0); // Shafii (standard)
this.setHanafi(1); // Hanafi
// Adjusting Methods for Higher Latitudes
this.setNone(0); // No adjustment
this.setMidNight(1); // middle of night
this.setOneSeventh(2); // 1/7th of night
this.setAngleBased(3); // angle/60th of night
// Time Formats
this.setTime24(0); // 24-hour format
this.setTime12(1); // 12-hour format
this.setTime12NS(2); // 12-hour format with no suffix
this.setFloating(3); // floating point number
// Time Names
_timeNames = new List<String>();
_timeNames.add("Fajr");
_timeNames.add("Sunrise");
_timeNames.add("Dhuhr");
_timeNames.add("Asr");
_timeNames.add("Sunset");
_timeNames.add("Maghrib");
_timeNames.add("Isha");
_invalidTime = "-----"; // The string used for invalid times
// --------------------- Technical Settings --------------------
this.setNumIterations(1); // number of iterations needed to compute
// times
// ------------------- Calc Method Parameters --------------------
// Tuning offsets {fajr, sunrise, dhuhr, asr, sunset, maghrib, isha}
_offsets = new List<int>(7);
_offsets[0] = 0;
_offsets[1] = 0;
_offsets[2] = 0;
_offsets[3] = 0;
_offsets[4] = 0;
_offsets[5] = 0;
_offsets[6] = 0;
/*
*
* fa : fajr angle ms : maghrib selector (0 = angle; 1 = minutes after
* sunset) mv : maghrib parameter value (in angle or minutes) is : isha
* selector (0 = angle; 1 = minutes after maghrib) iv : isha parameter
* value (in angle or minutes)
*/
_methodParams = new HashMap<int, List<double>>();
// Jafari
List<double> _jValues = [16, 0, 4, 0, 14];
_methodParams[this.getJafari()] = _jValues;
// Karachi
List<double> _kValues = [18, 1, 0, 0, 18];
_methodParams[this.getKarachi()] = _kValues;
// ISNA
List<double> _iValues = [15, 1, 0, 0, 15];
_methodParams[this.getISNA()] = _iValues;
// MWL
List<double> _mwValues = [18, 1, 0, 0, 17];
_methodParams[this.getMWL()] = _mwValues;
// Makkah
List<double> _mkValues = [18.5, 1, 0, 1, 90];
_methodParams[this.getMakkah()] = _mkValues;
// Egypt
List<double> _eValues = [19.5, 1, 0, 0, 17.5];
_methodParams[this.getEgypt()] = _eValues;
// Tehran
List<double> _tValues = [17.7, 0, 4.5, 0, 14];
_methodParams[this.getTehran()] = _tValues;
// Custom
List<double> _cValues = [18, 1, 0, 0, 17];
_methodParams[this.getCustom()] = _cValues;
}
// ---------------------- Trigonometric Functions -----------------------
// range reduce angle in degrees.
double _fixAngle(double a) {
a = a - (360 * ((a / 360.0).floor()));
a = a < 0 ? (a + 360) : a;
return a;
}
//range reduce hours to 0..23
double _fixHour(double a) {
a = a - 24.0 * (a / 24.0).floor();
a = a < 0 ? (a + 24) : a;
return a;
}
// radian to degree
double _radiansToDegrees(double alpha) {
return ((alpha * 180.0) / math.pi);
}
// deree to radian
double _degreesToRadians(double alpha) {
return ((alpha * math.pi) / 180.0);
}
// degree sin
double _dsin(double d) {
return (math.sin(_degreesToRadians(d)));
}
// degree cos
double _dcos(double d) {
return (math.cos(_degreesToRadians(d)));
}
// degree tan
double _dtan(double d) {
return (math.tan(_degreesToRadians(d)));
}
// degree arcsin
double _darcsin(double x) {
double val = math.asin(x);
return _radiansToDegrees(val);
}
// degree arccos
double darccos(double x) {
double val = math.acos(x);
return _radiansToDegrees(val);
}
// degree arctan
double _darctan(double x) {
double val = math.atan(x);
return _radiansToDegrees(val);
}
// degree arctan2
double _darctan2(double y, double x) {
double val = math.atan2(y, x);
return _radiansToDegrees(val);
}
// degree arccot
double darccot(double x) {
double val = math.atan2(1.0, x);
return _radiansToDegrees(val);
}
// ---------------------- Time-Zone Functions -----------------------
// compute local time-zone for a specific date
/* getTimeZone1() {
TimeZone timez = TimeZone.;
double hoursDiff = (timez.getRawOffset() / 1000.0) / 3600;
return hoursDiff;
}
// compute base time-zone of the system
getBaseTimeZone() {
TimeZone timez = TimeZone.getDefault();
double hoursDiff = (timez.getRawOffset() / 1000.0) / 3600;
return hoursDiff;
}
// detect daylight saving in a given date
detectDaylightSaving() {
TimeZone timez = TimeZone.UTC;
double hoursDiff = timez.getDSTSavings();
return hoursDiff;
}*/
// ---------------------- Julian Date Functions -----------------------
// calculate julian date from a calendar date
julianDate(int year, int month, int day) {
if (month <= 2) {
year -= 1;
month += 12;
}
double A = (year / 100.0).floorToDouble();
double B = 2 - A + (A / 4.0).floor();
double JD = (365.25 * (year + 4716)).floor() +
(30.6001 * (month + 1)).floor() +
day +
B -
1524.5;
return JD;
}
/*// convert a calendar date to julian date (second method)
calcJD(int year, int month, int day) {
double J1970 = 2440588.0;
Date date = new Date(year, month - 1, day);
double ms = date.getTime(); // # of milliseconds since midnight Jan 1,
// 1970
double days = (ms / (1000.0 * 60.0 * 60.0 * 24.0)).floorToDouble();
return J1970 + days - 0.5;
}*/
//
// ---------------------- Calculation Functions -----------------------
// ---------------------- Calculation Functions -----------------------
// References:
// http://www.ummah.net/astronomy/saltime
// http://aa.usno.navy.mil/faq/docs/SunApprox.html
// compute declination angle of sun and equation of time
List<double> sunPosition(double jd) {
double D = jd - 2451545;
double g = _fixAngle(357.529 + 0.98560028 * D);
double q = _fixAngle(280.459 + 0.98564736 * D);
double L = _fixAngle(q + (1.915 * _dsin(g)) + (0.020 * _dsin(2 * g)));
// double R = 1.00014 - 0.01671 * [self dcos:g] - 0.00014 * [self dcos:
// (2*g)];
double e = 23.439 - (0.00000036 * D);
double d = _darcsin(_dsin(e) * _dsin(L));
double RA = (_darctan2((_dcos(e) * _dsin(L)), (_dcos(L)))) / 15.0;
RA = _fixHour(RA);
double EqT = q / 15.0 - RA;
List<double> sPosition = new List(2);
sPosition[0] = d;
sPosition[1] = EqT;
return sPosition;
}
// compute equation of time
double equationOfTime(double jd) {
double eq = sunPosition(jd)[1];
return eq;
}
// compute declination angle of sun
double sunDeclination(double jd) {
double d = sunPosition(jd)[0];
return d;
}
// compute mid-day (Dhuhr, Zawal) time
double computeMidDay(double t) {
double T = equationOfTime(this.getJDate() + t);
double Z = _fixHour(12 - T);
return Z;
}
// compute time for a given angle G
double computeTime(double G, double t) {
double D = sunDeclination(this.getJDate() + t);
double Z = computeMidDay(t);
double Beg = -_dsin(G) - _dsin(D) * _dsin(this.getLat());
double Mid = _dcos(D) * _dcos(this.getLat());
double V = darccos(Beg / Mid) / 15.0;
return Z + (G > 90 ? -V : V);
}
// compute the time of Asr
// Shafii: step=1, Hanafi: step=2
double computeAsr(double step, double t) {
double D = sunDeclination(this.getJDate() + t);
double G = -darccot(step + _dtan((this.getLat() - D).abs()));
return computeTime(G, t);
}
// ---------------------- Misc Functions -----------------------
// compute the difference between two times
double timeDiff(double time1, double time2) {
return _fixHour(time2 - time1);
}
// -------------------- Interface Functions --------------------
// return prayer times for a given date
List<String> getDatePrayerTimes(int year, int month, int day, double latitude,
double longitude, double tZone) {
this.setLat(latitude);
this.setLng(longitude);
this.setTimeZone(tZone);
this.setJDate(julianDate(year, month, day));
double lonDiff = longitude / (15.0 * 24.0);
this.setJDate(this.getJDate() - lonDiff);
return computeDayTimes();
}
// return prayer times for a given date
List<String> getPrayerTimes(
DateTime date, double latitude, double longitude, double tZone) {
int year = date.year;
int month = date.month;
int day = date.day;
return getDatePrayerTimes(year, month, day, latitude, longitude, tZone);
}
// set custom values for calculation parameters
void setCustomParams(List<double> params) {
for (int i = 0; i < 5; i++) {
if (params[i] == null) {
params[i] = _methodParams[this._calcMethod][i];
_methodParams[this.getCustom()] = params;
} else {
_methodParams[this.getCustom()][i] = params[i];
}
}
this.setCalcMethod(this.getCustom());
}
// set the angle for calculating Fajr
void setFajrAngle(double angle) {
List<double> params = [angle, -1, -1, -1, -1];
setCustomParams(params);
}
// set the angle for calculating Maghrib
void setMaghribAngle(double angle) {
List<double> params = [-1, 0, angle, -1, -1];
setCustomParams(params);
}
// set the angle for calculating Isha
void setIshaAngle(double angle) {
List<double> params = [-1, -1, -1, 0, angle];
setCustomParams(params);
}
// set the minutes after Sunset for calculating Maghrib
void setMaghribMinutes(double minutes) {
List<double> params = [-1, 1, minutes, -1, -1];
setCustomParams(params);
}
// set the minutes after Maghrib for calculating Isha
void setIshaMinutes(double minutes) {
List<double> params = [-1, -1, -1, 1, minutes];
setCustomParams(params);
}
// convert double hours to 24h format
String floatToTime24(double time) {
String result;
if (time == double.nan) {
return _invalidTime;
}
time = _fixHour(time + 0.5 / 60.0); // add 0.5 minutes to round
int hours = time.floor();
double minutes = ((time - hours) * 60.0).floorToDouble();
if ((hours >= 0 && hours <= 9) && (minutes >= 0 && minutes <= 9)) {
result = "0" + hours.toString() + ":0" + (minutes).round().toString();
} else if ((hours >= 0 && hours <= 9)) {
result = "0" + hours.toString() + ":" + (minutes).round().toString();
} else if ((minutes >= 0 && minutes <= 9)) {
result = hours.toString() + ":0" + (minutes).round().toString();
} else {
result = hours.toString() + ":" + (minutes).round().toString();
}
return result;
}
// convert double hours to 12h format
String floatToTime12(double time, bool noSuffix) {
if (time == double.nan) {
return _invalidTime;
}
time = _fixHour(time + 0.5 / 60); // add 0.5 minutes to round
int hours = (time).floor();
double minutes = ((time - hours) * 60).floorToDouble();
String suffix, result;
if (hours >= 12) {
suffix = "PM";
} else {
suffix = "AM";
}
hours = ((((hours + 12) - 1) % (12)) + 1);
/*hours = (hours + 12) - 1;
int hrs = (int) hours % 12;
hrs += 1;*/
if (noSuffix == false) {
if ((hours >= 0 && hours <= 9) && (minutes >= 0 && minutes <= 9)) {
result = "0" +
hours.toString() +
":0" +
(minutes).round().toString() +
" " +
suffix;
} else if ((hours >= 0 && hours <= 9)) {
result = "0" +
hours.toString() +
":" +
(minutes).round().toString() +
" " +
suffix;
} else if ((minutes >= 0 && minutes <= 9)) {
result = hours.toString() +
":0" +
(minutes).round().toString() +
" " +
suffix;
} else {
result = hours.toString() +
":" +
(minutes).round().toString() +
" " +
suffix;
}
} else {
if ((hours >= 0 && hours <= 9) && (minutes >= 0 && minutes <= 9)) {
result = "0" + hours.toString() + ":0" + (minutes).round().toString();
} else if ((hours >= 0 && hours <= 9)) {
result = "0" + hours.toString() + ":" + (minutes).round().toString();
} else if ((minutes >= 0 && minutes <= 9)) {
result = hours.toString() + ":0" + (minutes).round().toString();
} else {
result = hours.toString() + ":" + (minutes).round().toString();
}
}
return result;
}
// convert double hours to 12h format with no suffix
String floatToTime12NS(double time) {
return floatToTime12(time, true);
}
// ---------------------- Compute Prayer Times -----------------------
// compute prayer times at given julian date
List<double> computeTimes(List<double> times) {
List<double> t = dayPortion(times);
double Fajr =
this.computeTime(180 - _methodParams[this.getCalcMethod()][0], t[0]);
double Sunrise = this.computeTime(180 - 0.833, t[1]);
double Dhuhr = this.computeMidDay(t[2]);
double Asr = this.computeAsr((1 + this.getAsrJuristic()).toDouble(), t[3]);
double Sunset = this.computeTime(0.833, t[4]);
double Maghrib =
this.computeTime(_methodParams[this.getCalcMethod()][2], t[5]);
double Isha =
this.computeTime(_methodParams[this.getCalcMethod()][4], t[6]);
List<double> CTimes = [Fajr, Sunrise, Dhuhr, Asr, Sunset, Maghrib, Isha];
return CTimes;
}
// compute prayer times at given julian date
List<String> computeDayTimes() {
List<double> times = [5, 6, 12, 13, 18, 18, 18]; // default times
for (int i = 1; i <= this.getNumIterations(); i++) {
times = computeTimes(times);
}
times = adjustTimes(times);
times = tuneTimes(times);
return adjustTimesFormat(times);
}
// adjust times in a prayer time array
List<double> adjustTimes(List<double> times) {
for (int i = 0; i < times.length; i++) {
times[i] += this.getTimeZone() - this.getLng() / 15;
}
times[2] += this.getDhuhrMinutes() / 60; // Dhuhr
if (_methodParams[this.getCalcMethod()][1] == 1) {
times[5] = times[4] + _methodParams[this.getCalcMethod()][2] / 60;
}
if (_methodParams[this.getCalcMethod()][3] == 1) {
times[6] = times[5] + _methodParams[this.getCalcMethod()][4] / 60;
}
if (this.getAdjustHighLats() != this.getNone()) {
times = adjustHighLatTimes(times);
}
return times;
}
// convert times array to given time format
List<String> adjustTimesFormat(List<double> times) {
List<String> result = new List<String>();
if (this.getTimeFormat() == this.getFloating()) {
for (double time in times) {
result.add(time.toString());
}
return result;
}
for (int i = 0; i < 7; i++) {
if (this.getTimeFormat() == this.getTime12()) {
result.add(floatToTime12(times[i], false));
} else if (this.getTimeFormat() == this.getTime12NS()) {
result.add(floatToTime12(times[i], true));
} else {
result.add(floatToTime24(times[i]));
}
}
return result;
}
// adjust Fajr, Isha and Maghrib for locations in higher latitudes
List<double> adjustHighLatTimes(List<double> times) {
double nightTime = timeDiff(times[4], times[1]); // sunset to sunrise
// Adjust Fajr
double FajrDiff =
nightPortion(_methodParams[this.getCalcMethod()][0]) * nightTime;
if (times[0] == double.nan || timeDiff(times[0], times[1]) > FajrDiff) {
times[0] = times[1] - FajrDiff;
}
// Adjust Isha
double IshaAngle = (_methodParams[this.getCalcMethod()][3] == 0)
? _methodParams[this.getCalcMethod()][4]
: 18;
double IshaDiff = this.nightPortion(IshaAngle) * nightTime;
if (times[6] == double.nan ||
this.timeDiff(times[4], times[6]) > IshaDiff) {
times[6] = times[4] + IshaDiff;
}
// Adjust Maghrib
double MaghribAngle = (_methodParams[this.getCalcMethod()][1] == 0)
? _methodParams[(this.getCalcMethod())][2]
: 4;
double MaghribDiff = nightPortion(MaghribAngle) * nightTime;
if (times[5] == double.nan ||
this.timeDiff(times[4], times[5]) > MaghribDiff) {
times[5] = times[4] + MaghribDiff;
}
return times;
}
// the night portion used for adjusting times in higher latitudes
double nightPortion(double angle) {
double calc = 0;
if (_adjustHighLats == _angleBased)
calc = (angle) / 60.0;
else if (_adjustHighLats == _midNight)
calc = 0.5;
else if (_adjustHighLats == _oneSeventh) calc = 0.14286;
return calc;
}
// convert hours to day portions
List<double> dayPortion(List<double> times) {
for (int i = 0; i < 7; i++) {
times[i] /= 24;
}
return times;
}
// Tune timings for adjustments
// Set time offsets
void tune(List<int> offsetTimes) {
for (int i = 0; i < offsetTimes.length; i++) {
// offsetTimes length
// should be 7 in order
// of Fajr, Sunrise,
// Dhuhr, Asr, Sunset,
// Maghrib, Isha
this._offsets[i] = offsetTimes[i];
}
}
List<double> tuneTimes(List<double> times) {
for (int i = 0; i < times.length; i++) {
times[i] = times[i] + this._offsets[i] / 60.0;
}
return times;
}
int getCalcMethod() {
return _calcMethod;
}
void setCalcMethod(int calcMethod) {
_calcMethod = calcMethod;
}
int getAsrJuristic() {
return _asrJuristic;
}
void setAsrJuristic(int asrJuristic) {
_asrJuristic = asrJuristic;
}
int getDhuhrMinutes() {
return _dhuhrMinutes;
}
void setDhuhrMinutes(int dhuhrMinutes) {
_dhuhrMinutes = dhuhrMinutes;
}
int getAdjustHighLats() {
return _adjustHighLats;
}
void setAdjustHighLats(int adjustHighLats) {
_adjustHighLats = adjustHighLats;
}
int getTimeFormat() {
return _timeFormat;
}
setTimeFormat(int timeFormat) {
_timeFormat = timeFormat;
}
double getLat() {
return _lat;
}
void setLat(double lat) {
_lat = lat;
}
double getLng() {
return _lng;
}
void setLng(double lng) {
_lng = lng;
}
double getTimeZone() {
return _timeZone;
}
void setTimeZone(double timeZone) {
_timeZone = timeZone;
}
double getJDate() {
return _jDate;
}
void setJDate(double jDate) {
_jDate = jDate;
}
int getJafari() {
return _jafri;
}
void setJafari(int jafari) {
_jafri = jafari;
}
int getKarachi() {
return _karachi;
}
void setKarachi(int karachi) {
_karachi = karachi;
}
int getISNA() {
return _iSNA;
}
void setISNA(int iSNA) {
_iSNA = iSNA;
}
int getMWL() {
return _mWL;
}
void setMWL(int mWL) {
_mWL = mWL;
}
int getMakkah() {
return _makkah;
}
void setMakkah(int makkah) {
_makkah = makkah;
}
int getEgypt() {
return _egypt;
}
void setEgypt(int egypt) {
_egypt = egypt;
}
int getCustom() {
return _custom;
}
void setCustom(int custom) {
_custom = custom;
}
int getTehran() {
return _tehran;
}
void setTehran(int tehran) {
_tehran = tehran;
}
int getShafii() {
return _shaffi;
}
void setShafii(int shafii) {
_shaffi = shafii;
}
int getHanafi() {
return _hanafi;
}
void setHanafi(int hanafi) {
_hanafi = hanafi;
}
int getNone() {
return _none;
}
void setNone(int none) {
_none = none;
}
int getMidNight() {
return _midNight;
}
void setMidNight(int midNight) {
_midNight = midNight;
}
int getOneSeventh() {
return _oneSeventh;
}
void setOneSeventh(int oneSeventh) {
_oneSeventh = oneSeventh;
}
int getAngleBased() {
return _angleBased;
}
void setAngleBased(int angleBased) {
_angleBased = angleBased;
}
int getTime24() {
return _time24;
}
void setTime24(int time24) {
_time24 = time24;
}
int getTime12() {
return _time12;
}
void setTime12(int time12) {
_time12 = time12;
}
int getTime12NS() {
return _time12Ns;
}
void setTime12NS(int time12ns) {
_time12Ns = time12ns;
}
int getFloating() {
return _floating;
}
void setFloating(int floating) {
_floating = floating;
}
int getNumIterations() {
return _numIterations;
}
void setNumIterations(int numIterations) {
_numIterations = numIterations;
}
List<String> getTimeNames() {
return _timeNames;
}
}```

Related

Cant get collisions to work for Mario-like game

so, I've spent a fair few hours on my Mario-like game but recently I've been stuck on the collisions after I changed to an object based collision system that seems like it should work but there is a bug somewhere that i cant find.
currently the box that represents the player just falls straight through the platform rather than sitting on the platform
You wont be able to run this snippet because I'm new to stack overflow and couldn't find anything closer to processing.
Here is the box class that has all my collision detection
//Box class -- THIS IS WHERE I NEED HELP -- everything else is just for context
//Box class
class Box {
private float xpos, ypos, sizeX, sizeY;
private float bottom = ypos + sizeY;
private float top = ypos;
private float left = xpos;
private float right = xpos + sizeX;
Box(float startX, float startY, float xSize, float ySize) {
boxes++;
xpos = startX;
ypos = startY;
sizeX = xSize;
sizeY = ySize;
}
void update() {
rect(xpos, ypos, sizeX, sizeY);
}
void collision() {
//If on box level
if (player.playerY + player.playerHeight >= top && player.playerY <= bottom) {
//Left Side
if ((player.playerX + player.playerWidth) <= left && (player.playerX + player.playerWidth) + speed >= left) {
player.playerX = left - player.playerWidth;
player.canMoveRight = false;
}
//Right Side
if (player.playerX >= right && player.playerX + speed <= right) {
player.playerX = right;
player.canMoveLeft = false;
}
}
//If in box Y coord
if (player.playerX + player.playerWidth >= left && player.playerX <= right) {
//top
if (player.playerY + player.playerHeight <= top && player.playerY + player.yVelocity + gravity >= top) {
player.Gravity = false;
player.playerY = top - player.playerHeight;
player.yVelocity = 0;
player.canMoveDown = false;
}
//bottom
if (player.playerY + player.yVelocity >= bottom && player.playerY + player.yVelocity + gravity <= bottom) {
player.canMoveUp = false;
player.yVelocity = 0;
player.playerY = bottom;
}
}
//onGround
if (player.playerY == ypos - player.playerHeight) {
player.onGround = true;
}
}
}
Control structure for multiple keypresses
//Control structure to enable multiple keypresses
//Control
float speed = 4;
float gravity = 1;
float jump = 10;
boolean isUp, isLeft, isDown, isRight;
void control() {
//Controls
if (isUp) {
if (player.canMoveUp) {
if (player.onGround) {
player.Gravity = true;
player.yVelocity = 0 + jump;
player.onGround = false;
}
}
}
if (isDown) {
if (player.canMoveDown) {
}
}
if (isRight) {
if (player.canMoveRight) {
player.playerX += speed;
}
}
if (isLeft) {
if (player.canMoveLeft) {
player.playerX -= speed;
}
}
if (player.onGround) {
player.Gravity = false;
player.yVelocity = 0;
}
}
void keyPressed() {
setMove(keyCode, true);
}
void keyReleased() {
setMove(keyCode, false);
}
boolean setMove(int k, boolean b) {
switch (k) {
case UP:
return isUp = b;
case DOWN:
return isDown = b;
case LEFT:
return isLeft = b;
case RIGHT:
return isRight = b;
default:
return b;
}
}
Main tab, box/entity updates and player class
//Main tab
float boxes = 0;
//Calls classes
Box b = new Box(0, 700, 800, 100);
Box b1 = new Box(300, 675, 25, 25);
Player player = new Player(50, 400, 20, 20);
void setup() {
size(800, 800);
frameRate(60);
}
void draw() {
background(255, 255, 255);
boxesUpdate();
boxesCollision();
entityUpdate();
control();
println(player.playerX + ", " + player.playerY);
println(player.yVelocity + ", " + player.Gravity + ", " + player.onGround + ", " + player.canMoveDown);
}
//Box collision update method for when i add more boxes
void boxesCollision() {
player.Gravity = true;
player.canMoveUp = true;
player.canMoveDown = true;
player.canMoveLeft = true;
player.canMoveRight = true;
player.onGround = false;
b.collision();
b1.collision();
if (player.Gravity) {
player.playerY += player.yVelocity;
player.yVelocity += gravity;
}
}
//Along with another update method for the other parts of the boxes
void boxesUpdate() {
b.update();
b1.update();
}
//Entity update method to update players and for when i add NPCs and enemies
void entityUpdate() {
player.update();
}
//Player class
class Player {
private float playerX, playerY, playerWidth, playerHeight;
private float yVelocity = 0;
private float xVelocity = 0;
private boolean canMoveRight, canMoveLeft, canMoveUp, canMoveDown;
private boolean onGround, Gravity;
Player(float X, float Y, float xSize, float ySize) {
playerWidth = xSize;
playerHeight = ySize;
playerX = X;
playerY = Y;
}
void update() {
rect(playerX, playerY, playerWidth, playerHeight);
}
}

Libgdx loader for Animation.class

I need to set loader in assetmanager for Animation.class, i used Gifloader,that loads completly animation from GifDecoder(that creates animation from gif)
but get error:
https://i.stack.imgur.com/HkrWe.png
, error on build: https://i.stack.imgur.com/2Mpaz.png
setloader line:
manager.setLoader(Animation.class, new Gifloader(new InternalFileHandleResolver()))
Gifloader class:
package com.mygdx.testgame;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.assets.AssetLoaderParameters;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.assets.loaders.AsynchronousAssetLoader;
import com.badlogic.gdx.assets.loaders.FileHandleResolver;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Array;
public class Gifloader extends AsynchronousAssetLoader<Animation<TextureRegion>, Gifloader.GifloaderParameter> {
private com.badlogic.gdx.graphics.g2d.Animation<TextureRegion> animresult;
public Gifloader(FileHandleResolver resolver) {
super(resolver);
}
#Override
public void loadAsync(AssetManager manager, String fileName, FileHandle file, GifloaderParameter parameter) {
animresult = (com.holidaystudios.tools.GifDecoder.loadGIFAnimation(Animation.PlayMode.LOOP,file.read()));
}
#Override
public Animation loadSync(AssetManager manager, String fileName, FileHandle file, GifloaderParameter parameter) {
return animresult;
}
#Override
public Array<AssetDescriptor> getDependencies(String fileName, FileHandle file, GifloaderParameter parameter) {
return null;
}
static public class GifloaderParameter extends AssetLoaderParameters<Animation<TextureRegion>> {
}
}
GifDecoder class:
/* Copyright by Johannes Borchardt */
/* LibGdx conversion 2014 by Anton Persson */
/* Released under Apache 2.0 */
/* https://code.google.com/p/animated-gifs-in-android/ */
package com.holidaystudios.tools;
import java.io.InputStream;
import java.util.Vector;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Animation.PlayMode;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.Array;
public class GifDecoder {
/**
* File read status: No errors.
*/
public static final int STATUS_OK = 0;
/**
* File read status: Error decoding file (may be partially decoded)
*/
public static final int STATUS_FORMAT_ERROR = 1;
/**
* File read status: Unable to open source.
*/
public static final int STATUS_OPEN_ERROR = 2;
/** max decoder pixel stack size */
protected static final int MAX_STACK_SIZE = 4096;
protected InputStream in;
protected int status;
protected int width; // full image width
protected int height; // full image height
protected boolean gctFlag; // global color table used
protected int gctSize; // size of global color table
protected int loopCount = 1; // iterations; 0 = repeat forever
protected int[] gct; // global color table
protected int[] lct; // local color table
protected int[] act; // active color table
protected int bgIndex; // background color index
protected int bgColor; // background color
protected int lastBgColor; // previous bg color
protected int pixelAspect; // pixel aspect ratio
protected boolean lctFlag; // local color table flag
protected boolean interlace; // interlace flag
protected int lctSize; // local color table size
protected int ix, iy, iw, ih; // current image rectangle
protected int lrx, lry, lrw, lrh;
protected DixieMap image; // current frame
protected DixieMap lastPixmap; // previous frame
protected byte[] block = new byte[256]; // current data block
protected int blockSize = 0; // block size last graphic control extension info
protected int dispose = 0; // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev
protected int lastDispose = 0;
protected boolean transparency = false; // use transparent color
protected int delay = 0; // delay in milliseconds
protected int transIndex; // transparent color index
// LZW decoder working arrays
protected short[] prefix;
protected byte[] suffix;
protected byte[] pixelStack;
protected byte[] pixels;
protected Vector<GifFrame> frames; // frames read from current file
protected int frameCount;
private static class DixieMap extends Pixmap {
DixieMap(int w, int h, Pixmap.Format f) {
super(w, h, f);
}
DixieMap(int[] data, int w, int h, Pixmap.Format f) {
super(w, h, f);
int x, y;
for(y = 0; y < h; y++) {
for(x = 0; x < w; x++) {
int pxl_ARGB8888 = data[x + y * w];
int pxl_RGBA8888 =
((pxl_ARGB8888 >> 24) & 0x000000ff) | ((pxl_ARGB8888 << 8) & 0xffffff00);
// convert ARGB8888 > RGBA8888
drawPixel(x, y, pxl_RGBA8888);
}
}
}
void getPixels(int[] pixels, int offset, int stride, int x, int y, int width, int height) {
java.nio.ByteBuffer bb = getPixels();
int k, l;
for(k = y; k < y + height; k++) {
int _offset = offset;
for(l = x; l < x + width; l++) {
int pxl = bb.getInt(4 * (l + k * width));
// convert RGBA8888 > ARGB8888
pixels[_offset++] = ((pxl >> 8) & 0x00ffffff) | ((pxl << 24) & 0xff000000);
}
offset += stride;
}
}
}
private static class GifFrame {
public GifFrame(DixieMap im, int del) {
image = im;
delay = del;
}
public DixieMap image;
public int delay;
}
/**
* Gets display duration for specified frame.
*
* #param n
* int index of frame
* #return delay in milliseconds
*/
public int getDelay(int n) {
delay = -1;
if ((n >= 0) && (n < frameCount)) {
delay = frames.elementAt(n).delay;
}
return delay;
}
/**
* Gets the number of frames read from file.
*
* #return frame count
*/
public int getFrameCount() {
return frameCount;
}
/**
* Gets the first (or only) image read.
*
* #return BufferedPixmap containing first frame, or null if none.
*/
public Pixmap getPixmap() {
return getFrame(0);
}
/**
* Gets the "Netscape" iteration count, if any. A count of 0 means repeat indefinitely.
*
* #return iteration count if one was specified, else 1.
*/
public int getLoopCount() {
return loopCount;
}
/**
* Creates new frame image from current data (and previous frames as specified by their disposition codes).
*/
protected void setPixels() {
// expose destination image's pixels as int array
int[] dest = new int[width * height];
// fill in starting image contents based on last image's dispose code
if (lastDispose > 0) {
if (lastDispose == 3) {
// use image before last
int n = frameCount - 2;
if (n > 0) {
lastPixmap = getFrame(n - 1);
} else {
lastPixmap = null;
}
}
if (lastPixmap != null) {
lastPixmap.getPixels(dest, 0, width, 0, 0, width, height);
// copy pixels
if (lastDispose == 2) {
// fill last image rect area with background color
int c = 0;
if (!transparency) {
c = lastBgColor;
}
for (int i = 0; i < lrh; i++) {
int n1 = (lry + i) * width + lrx;
int n2 = n1 + lrw;
for (int k = n1; k < n2; k++) {
dest[k] = c;
}
}
}
}
}
// copy each source line to the appropriate place in the destination
int pass = 1;
int inc = 8;
int iline = 0;
for (int i = 0; i < ih; i++) {
int line = i;
if (interlace) {
if (iline >= ih) {
pass++;
switch (pass) {
case 2:
iline = 4;
break;
case 3:
iline = 2;
inc = 4;
break;
case 4:
iline = 1;
inc = 2;
break;
default:
break;
}
}
line = iline;
iline += inc;
}
line += iy;
if (line < height) {
int k = line * width;
int dx = k + ix; // start of line in dest
int dlim = dx + iw; // end of dest line
if ((k + width) < dlim) {
dlim = k + width; // past dest edge
}
int sx = i * iw; // start of line in source
while (dx < dlim) {
// map color and insert in destination
int index = ((int) pixels[sx++]) & 0xff;
int c = act[index];
if (c != 0) {
dest[dx] = c;
}
dx++;
}
}
}
image = new DixieMap(dest, width, height, Pixmap.Format.RGBA8888);
//Pixmap.createPixmap(dest, width, height, Config.ARGB_4444);
}
/**
* Gets the image contents of frame n.
*
* #return BufferedPixmap representation of frame, or null if n is invalid.
*/
public DixieMap getFrame(int n) {
if (frameCount <= 0)
return null;
n = n % frameCount;
return ((GifFrame) frames.elementAt(n)).image;
}
/**
* Reads GIF image from stream
*
* #param is
* containing GIF file.
* #return read status code (0 = no errors)
*/
public int read(InputStream is) {
init();
if (is != null) {
in = is;
readHeader();
if (!err()) {
readContents();
if (frameCount < 0) {
status = STATUS_FORMAT_ERROR;
}
}
} else {
status = STATUS_OPEN_ERROR;
}
try {
is.close();
} catch (Exception e) {
}
return status;
}
/**
* Decodes LZW image data into pixel array. Adapted from John Cristy's BitmapMagick.
*/
protected void decodeBitmapData() {
int nullCode = -1;
int npix = iw * ih;
int available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, count, i, datum, data_size, first, top, bi, pi;
if ((pixels == null) || (pixels.length < npix)) {
pixels = new byte[npix]; // allocate new pixel array
}
if (prefix == null) {
prefix = new short[MAX_STACK_SIZE];
}
if (suffix == null) {
suffix = new byte[MAX_STACK_SIZE];
}
if (pixelStack == null) {
pixelStack = new byte[MAX_STACK_SIZE + 1];
}
// Initialize GIF data stream decoder.
data_size = read();
clear = 1 << data_size;
end_of_information = clear + 1;
available = clear + 2;
old_code = nullCode;
code_size = data_size + 1;
code_mask = (1 << code_size) - 1;
for (code = 0; code < clear; code++) {
prefix[code] = 0; // XXX ArrayIndexOutOfBoundsException
suffix[code] = (byte) code;
}
// Decode GIF pixel stream.
datum = bits = count = first = top = pi = bi = 0;
for (i = 0; i < npix;) {
if (top == 0) {
if (bits < code_size) {
// Load bytes until there are enough bits for a code.
if (count == 0) {
// Read a new data block.
count = readBlock();
if (count <= 0) {
break;
}
bi = 0;
}
datum += (((int) block[bi]) & 0xff) << bits;
bits += 8;
bi++;
count--;
continue;
}
// Get the next code.
code = datum & code_mask;
datum >>= code_size;
bits -= code_size;
// Interpret the code
if ((code > available) || (code == end_of_information)) {
break;
}
if (code == clear) {
// Reset decoder.
code_size = data_size + 1;
code_mask = (1 << code_size) - 1;
available = clear + 2;
old_code = nullCode;
continue;
}
if (old_code == nullCode) {
pixelStack[top++] = suffix[code];
old_code = code;
first = code;
continue;
}
in_code = code;
if (code == available) {
pixelStack[top++] = (byte) first;
code = old_code;
}
while (code > clear) {
pixelStack[top++] = suffix[code];
code = prefix[code];
}
first = ((int) suffix[code]) & 0xff;
// Add a new string to the string table,
if (available >= MAX_STACK_SIZE) {
break;
}
pixelStack[top++] = (byte) first;
prefix[available] = (short) old_code;
suffix[available] = (byte) first;
available++;
if (((available & code_mask) == 0) && (available < MAX_STACK_SIZE)) {
code_size++;
code_mask += available;
}
old_code = in_code;
}
// Pop a pixel off the pixel stack.
top--;
pixels[pi++] = pixelStack[top];
i++;
}
for (i = pi; i < npix; i++) {
pixels[i] = 0; // clear missing pixels
}
}
/**
* Returns true if an error was encountered during reading/decoding
*/
protected boolean err() {
return status != STATUS_OK;
}
/**
* Initializes or re-initializes reader
*/
protected void init() {
status = STATUS_OK;
frameCount = 0;
frames = new Vector<GifFrame>();
gct = null;
lct = null;
}
/**
* Reads a single byte from the input stream.
*/
protected int read() {
int curByte = 0;
try {
curByte = in.read();
} catch (Exception e) {
status = STATUS_FORMAT_ERROR;
}
return curByte;
}
/**
* Reads next variable length block from input.
*
* #return number of bytes stored in "buffer"
*/
protected int readBlock() {
blockSize = read();
int n = 0;
if (blockSize > 0) {
try {
int count = 0;
while (n < blockSize) {
count = in.read(block, n, blockSize - n);
if (count == -1) {
break;
}
n += count;
}
} catch (Exception e) {
e.printStackTrace();
}
if (n < blockSize) {
status = STATUS_FORMAT_ERROR;
}
}
return n;
}
/**
* Reads color table as 256 RGB integer values
*
* #param ncolors
* int number of colors to read
* #return int array containing 256 colors (packed ARGB with full alpha)
*/
protected int[] readColorTable(int ncolors) {
int nbytes = 3 * ncolors;
int[] tab = null;
byte[] c = new byte[nbytes];
int n = 0;
try {
n = in.read(c);
} catch (Exception e) {
e.printStackTrace();
}
if (n < nbytes) {
status = STATUS_FORMAT_ERROR;
} else {
tab = new int[256]; // max size to avoid bounds checks
int i = 0;
int j = 0;
while (i < ncolors) {
int r = ((int) c[j++]) & 0xff;
int g = ((int) c[j++]) & 0xff;
int b = ((int) c[j++]) & 0xff;
tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b;
}
}
return tab;
}
/**
* Main file parser. Reads GIF content blocks.
*/
protected void readContents() {
// read GIF file content blocks
boolean done = false;
while (!(done || err())) {
int code = read();
switch (code) {
case 0x2C: // image separator
readBitmap();
break;
case 0x21: // extension
code = read();
switch (code) {
case 0xf9: // graphics control extension
readGraphicControlExt();
break;
case 0xff: // application extension
readBlock();
String app = "";
for (int i = 0; i < 11; i++) {
app += (char) block[i];
}
if (app.equals("NETSCAPE2.0")) {
readNetscapeExt();
} else {
skip(); // don't care
}
break;
case 0xfe:// comment extension
skip();
break;
case 0x01:// plain text extension
skip();
break;
default: // uninteresting extension
skip();
}
break;
case 0x3b: // terminator
done = true;
break;
case 0x00: // bad byte, but keep going and see what happens break;
default:
status = STATUS_FORMAT_ERROR;
}
}
}
/**
* Reads Graphics Control Extension values
*/
protected void readGraphicControlExt() {
read(); // block size
int packed = read(); // packed fields
dispose = (packed & 0x1c) >> 2; // disposal method
if (dispose == 0) {
dispose = 1; // elect to keep old image if discretionary
}
transparency = (packed & 1) != 0;
delay = readShort() * 10; // delay in milliseconds
transIndex = read(); // transparent color index
read(); // block terminator
}
/**
* Reads GIF file header information.
*/
protected void readHeader() {
String id = "";
for (int i = 0; i < 6; i++) {
id += (char) read();
}
if (!id.startsWith("GIF")) {
status = STATUS_FORMAT_ERROR;
return;
}
readLSD();
if (gctFlag && !err()) {
gct = readColorTable(gctSize);
bgColor = gct[bgIndex];
}
}
/**
* Reads next frame image
*/
protected void readBitmap() {
ix = readShort(); // (sub)image position & size
iy = readShort();
iw = readShort();
ih = readShort();
int packed = read();
lctFlag = (packed & 0x80) != 0; // 1 - local color table flag interlace
lctSize = (int) Math.pow(2, (packed & 0x07) + 1);
// 3 - sort flag
// 4-5 - reserved lctSize = 2 << (packed & 7); // 6-8 - local color
// table size
interlace = (packed & 0x40) != 0;
if (lctFlag) {
lct = readColorTable(lctSize); // read table
act = lct; // make local table active
} else {
act = gct; // make global table active
if (bgIndex == transIndex) {
bgColor = 0;
}
}
int save = 0;
if (transparency) {
save = act[transIndex];
act[transIndex] = 0; // set transparent color if specified
}
if (act == null) {
status = STATUS_FORMAT_ERROR; // no color table defined
}
if (err()) {
return;
}
decodeBitmapData(); // decode pixel data
skip();
if (err()) {
return;
}
frameCount++;
// create new image to receive frame data
image = new DixieMap(width, height, Pixmap.Format.RGBA8888);
setPixels(); // transfer pixel data to image
frames.addElement(new GifFrame(image, delay)); // add image to frame
// list
if (transparency) {
act[transIndex] = save;
}
resetFrame();
}
/**
* Reads Logical Screen Descriptor
*/
protected void readLSD() {
// logical screen size
width = readShort();
height = readShort();
// packed fields
int packed = read();
gctFlag = (packed & 0x80) != 0; // 1 : global color table flag
// 2-4 : color resolution
// 5 : gct sort flag
gctSize = 2 << (packed & 7); // 6-8 : gct size
bgIndex = read(); // background color index
pixelAspect = read(); // pixel aspect ratio
}
/**
* Reads Netscape extenstion to obtain iteration count
*/
protected void readNetscapeExt() {
do {
readBlock();
if (block[0] == 1) {
// loop count sub-block
int b1 = ((int) block[1]) & 0xff;
int b2 = ((int) block[2]) & 0xff;
loopCount = (b2 << 8) | b1;
}
} while ((blockSize > 0) && !err());
}
/**
* Reads next 16-bit value, LSB first
*/
protected int readShort() {
// read 16-bit value, LSB first
return read() | (read() << 8);
}
/**
* Resets frame state for reading next image.
*/
protected void resetFrame() {
lastDispose = dispose;
lrx = ix;
lry = iy;
lrw = iw;
lrh = ih;
lastPixmap = image;
lastBgColor = bgColor;
dispose = 0;
transparency = false;
delay = 0;
lct = null;
}
/**
* Skips variable length blocks up to and including next zero length block.
*/
protected void skip() {
do {
readBlock();
} while ((blockSize > 0) && !err());
}
public Animation<TextureRegion> getAnimation(PlayMode playMode) {
int nrFrames = getFrameCount();
Pixmap frame = getFrame(0);
int width = frame.getWidth();
int height = frame.getHeight();
int vzones = (int)Math.sqrt((double)nrFrames);
int hzones = vzones;
while(vzones * hzones < nrFrames) vzones++;
int v, h;
Pixmap target = new Pixmap(width * hzones, height * vzones, Pixmap.Format.RGBA8888);
for(h = 0; h < hzones; h++) {
for(v = 0; v < vzones; v++) {
int frameID = v + h * vzones;
if(frameID < nrFrames) {
frame = getFrame(frameID);
target.drawPixmap(frame, h * width, v * height);
}
}
}
Texture texture = new Texture(target);
Array<TextureRegion> texReg = new Array<TextureRegion>();
for(h = 0; h < hzones; h++) {
for(v = 0; v < vzones; v++) {
int frameID = v + h * vzones;
if(frameID < nrFrames) {
TextureRegion tr = new TextureRegion(texture, h * width, v * height, width, height);
texReg.add(tr);
}
}
}
float frameDuration = (float)getDelay(0);
frameDuration /= 1000; // convert milliseconds into seconds
Animation<TextureRegion> result = new Animation<TextureRegion>(frameDuration, texReg, playMode);
return result;
}
public static Animation<TextureRegion> loadGIFAnimation(Animation.PlayMode playMode, InputStream is) {
GifDecoder gdec = new GifDecoder();
gdec.read(is);
return gdec.getAnimation(playMode);
}
}
please anyone help me
I could only make this work in the syncloader and not in the asyncloader is problably because it takes too much resources.
Too avoid the errors i made a GIF class to wrap the Animation this is also to dispose the texture when its no longer needed if this is not done it will create a memory leak.
public class GIF implements Disposable {
public Animation<TextureRegion> animation;
public Texture texture;
public GIF( Animation<TextureRegion> animation ) {
Object[] object = animation.getKeyFrames();
this.animation = animation;
this.texture = ((TextureRegion) object[ 0 ]).getTexture();
}
#Override
public void dispose() {
texture.dispose();
}
}
Here is the asset loader code:
public class Gifloader extends AsynchronousAssetLoader<GIF, Gifloader.GifloaderParameter> {
private Animation<TextureRegion> animation;
public Gifloader(FileHandleResolver resolver) {
super(resolver);
this.animation = null;
}
#Override
public void loadAsync(AssetManager manager, String fileName, FileHandle file, GifloaderParameter parameter) {
}
#Override
public GIF loadSync(AssetManager manager, String fileName, FileHandle file, GifloaderParameter parameter) {
PlayMode playMode = PlayMode.LOOP;
if ( parameter != null ){
playMode = parameter.playMode;
}
animation = (GifDecoder.loadGIFAnimation( playMode, file.read() ));
return new GIF( animation );
}
#SuppressWarnings( "rawtypes" )
#Override
public Array<AssetDescriptor> getDependencies(String fileName, FileHandle file, GifloaderParameter parameter) {
return null;
}
public static class GifloaderParameter extends AssetLoaderParameters<GIF> {
public PlayMode playMode = PlayMode.LOOP;
}
}

Kd Tree or Bounding Box Not Working Properly

Hope everyone is well.I am having a bit of an issue implementing the kd tree from pbrt v2.It's fast but all the normals on the model are wrong after rendering.The funny thing is if I change the values of pMin and pMax in the Bounding Box constructor,I get the correct model with the correct normals but the render takes substantially longer.I dont know what could be causing this.By the way pbrt v2 uses a left-handed coordinate system while I am using a right-handed coordinate system.I have tried changing my coordinate to left-handed and also importing models from a left-handed system instead of a right-handed system but the issue still remains.At one point it worked but the models positions were reversed.Its best to show you my code so u can better understand my dilemma.
*BOUNDING BOX CODE *
class BBox
{
public:
Point pMin,pMax;
BBox(){
pMin = Point(INFINITY,INFINITY,INFINITY);
pMax = Point(-INFINITY,-INFINITY,-INFINITY);
}
BBox(const Point& p) : pMin(p),pMax(p) { }
BBox(const Point& p1,const Point& p2) {
pMin = Point(min(p1.x,p2.x),min(p1.y,p2.y),min(p1.z,p2.z));
pMax = Point(max(p1.x,p2.x),max(p1.y,p2.y),max(p1.z,p2.z));
}
Point boxCentroid() const {
float x = (pMin.x+pMax.x)/2;
float y = (pMin.y+pMax.y)/2;
float z = (pMin.z+pMax.z)/2;
return Point(x,y,z);
}
BBox Union(const BBox &b,const Point& p) {
BBox ret = b;
ret.pMin.x = min(b.pMin.x,p.x);
ret.pMin.y = min(b.pMin.y,p.y);
ret.pMin.z = min(b.pMin.z,p.z);
ret.pMax.x = max(b.pMax.x,p.x);
ret.pMax.y = max(b.pMax.y,p.y);
ret.pMax.z = max(b.pMax.z,p.z);
return ret;
}
friend BBox Union(const BBox& b,const BBox& b2){
BBox ret;
ret.pMin.x = min(b.pMin.x, b2.pMin.x);
ret.pMin.y = min(b.pMin.y, b2.pMin.y);
ret.pMin.z = min(b.pMin.z, b2.pMin.z);
ret.pMax.x = max(b.pMax.x, b2.pMax.x);
ret.pMax.y = max(b.pMax.y, b2.pMax.y);
ret.pMax.z = max(b.pMax.z, b2.pMax.z);
return ret;
}
bool Overlaps(const BBox &b) const {
bool x = (pMax.x >= b.pMin.x) && (pMin.x <= b.pMax.x);
bool y = (pMax.y >= b.pMin.y) && (pMin.y <= b.pMax.y);
bool z = (pMax.z >= b.pMin.z) && (pMin.z <= b.pMax.z);
return (x && y && z);
}
bool Inside(const Point& pt) const {
return (pt.x >= pMin.x && pt.x <= pMax.x &&
pt.y >= pMin.y && pt.y <= pMax.y &&
pt.z >= pMin.z && pt.z <= pMax.z);
}
void Expand(float delta) {
pMin -= Vector(delta,delta,delta);
pMax += Vector(delta,delta,delta);
}
float SurfaceArea() const {
Vector d = pMax - pMin;
return 2.f * (d.x*d.y + d.x*d.z + d.y*d.z);
}
float Volume() const {
Vector d = pMax - pMin;
return d.x*d.y*d.z;
}
int MaximumExtent() const {
Vector diag = pMax - pMin;
if (diag.x > diag.y && diag.x > diag.z)
return 0;
else if (diag.y > diag.z)
return 1;
else
return 2;
}
const Point &operator[](int i) const {
//Assert(i == 0 || i == 1);
return (&pMin)[i];
}
Point &operator[](int i) {
//Assert(i == 0 || i == 1);
return (&pMin)[i];
}
Point Lerp(float tx, float ty, float tz) const {
return Point(::Lerp(tx, pMin.x, pMax.x), ::Lerp(ty, pMin.y, pMax.y),
::Lerp(tz, pMin.z, pMax.z));
}
Vector Offset(const Point &p) const {
return Vector((p.x - pMin.x) / (pMax.x - pMin.x),
(p.y - pMin.y) / (pMax.y - pMin.y),
(p.z - pMin.z) / (pMax.z - pMin.z));
}
void BBox::BoundingSphere(Point *c, float *rad) const {
*c = pMin * 0.5f + pMax * 0.5f;
*rad = Inside(*c) ? Distance(*c, pMax) : 0.f;
}
bool IntersectP(const Ray &ray,float *hitt0,float *hitt1) const {
float t0 = 0.00001f, t1 = INFINITY;
for (int i = 0; i < 3; ++i) {
// Update interval for _i_th bounding box slab
float invRayDir = 1.f / ray.d[i];
float tNear = (pMin[i] - ray.o[i]) * invRayDir;
float tFar = (pMax[i] - ray.o[i]) * invRayDir;
// Update parametric interval from slab intersection $t$s
if (tNear > tFar) swap(tNear, tFar);
t0 = tNear > t0 ? tNear : t0;
t1 = tFar < t1 ? tFar : t1;
if (t0 > t1) return false;
}
if (hitt0) *hitt0 = t0;
if (hitt1) *hitt1 = t1;
return true;
}
};
If I use the current default BBox constructor with the above pMin and pMax values.I get this
But if I change it to
pMin = Point(-INFINITY,-INFINITY,-INFINITY);
pMax = Point(INFINITY,INFINITY,INFINITY);
I get the right model.This...
But it takes substantially longer.(7secs to 51 minutes) You see the issue ??? Anyways I need help.Any help is appreciated.Thanks
Here is the rest of the necessary code (KD-TREE) and (CAMERA)
*KD TREE CODE *
struct BoundEdge
{
//BoundEdge Methods
BoundEdge() { }
BoundEdge(float tt,int pn,bool starting){
t = tt;
primNum = pn;
type = starting ? START : END;
}
bool operator<(const BoundEdge &e) const {
if (t == e.t)
return (int)type < (int)e.type;
else return t < e.t;
}
float t;
int primNum;
enum { START,END } type;
};
struct KdAccelNode
{
void initLeaf(uint32_t *primNums,int np,MemoryArena &arena);
void initInterior(uint32_t axis,uint32_t ac,float s)
{
split = s;
flags = axis;
aboveChild |= (ac<<2);
}
float SplitPos() const { return split; }
uint32_t nPrimitives() const { return nPrims >> 2; }
uint32_t SplitAxis() const { return flags & 3; }
bool isLeaf() const { return (flags & 3)==3; }
uint32_t AboveChild() const { return aboveChild >> 2; }
union{
float split;
uint32_t onePrimitive;
uint32_t *primitives;
};
private:
union{
uint32_t flags;
uint32_t nPrims;
uint32_t aboveChild;
};
};
struct KdToDo{
const KdAccelNode *node;
float tMIN,tMAX;
};
class KdTreeAccel : public Primitive
{
public:
KdTreeAccel(const vector<Primitive*> &p,int icost,int tcost,float ebonus,int maxp,int md)
:primitives(p),isectCost(icost),traversalCost(tcost),emptyBonus(ebonus),maxPrims(maxp),maxDepth(md)
{
//Build Kd-Tree
nextFreeNode = nAllocedNodes = 0;
if(maxDepth <= 0)
maxDepth = Round2Int(8+1.3f * Log2Int(float(primitives.size())));
//<Compute Bounds>
vector<BBox> primBounds;
primBounds.reserve(primitives.size());
for(uint32_t i=0;i<primitives.size();++i)
{
BBox b = primitives[i]->BoxBound();
bounds = Union(bounds,b);
primBounds.push_back(b);
}
//<Allocate Working Memory>
BoundEdge *edges[3];
for(int i=0;i<3;++i)
edges[i] = new BoundEdge[2*primitives.size()];
uint32_t *prims0 = new uint32_t[primitives.size()];
uint32_t *prims1 = new uint32_t[(maxDepth+1) * primitives.size()];
//<Initialize primNums
uint32_t *primNums = new uint32_t[primitives.size()];
for(uint32_t i=0;i<primitives.size();++i)
primNums[i] = i;
//<Start Recursive Construction
buildTree(0,bounds,primBounds,primNums,primitives.size(),maxDepth,edges,prims0,prims1);
//<Free Memory
delete[] primNums;
for (int i = 0; i < 3; ++i)
delete[] edges[i];
delete[] prims0;
delete[] prims1;
}
virtual bool intersect(const Ray& r,float t_min,float t_max,primitive_record &rec) const;
virtual bool intersect_p(const Ray& r,float t_min,float t_max) const;
virtual float area() const;
virtual Vector _normal(const Point& in_point) const;
virtual Point randomSamplePoint() const;
virtual BBox BoxBound() const ;
virtual Point centroid() const ;
private:
void buildTree(int nodeNum,const BBox &nodeBounds,const vector<BBox> &allPrimBounds,uint32_t *primNums,
int nPrimitives,int depth,BoundEdge *edges[3],uint32_t *prims0,uint32_t *prims1,
int badRefines=0);
int isectCost,traversalCost,maxPrims,maxDepth;
float emptyBonus;
vector<Primitive*> primitives;
KdAccelNode *nodes;
int nAllocedNodes,nextFreeNode;
BBox bounds;
MemoryArena arena;
};
void KdAccelNode::initLeaf(uint32_t *primNums,int np,MemoryArena &arena)
{
flags = 3;
nPrims |= (np<<2);
//Store primitive id for leaf node
if(np == 0)
onePrimitive = 0;
else if(np == 1)
onePrimitive = primNums[0];
else{
primitives = arena.Alloc<uint32_t>(np);
for(int i=0;i<np;++i)
primitives[i] = primNums[i];
}
}
void KdTreeAccel::buildTree(int nodeNum,const BBox &nodeBounds,const vector<BBox> &allPrimBounds,uint32_t *primNums,
int nPrimitives,int depth,BoundEdge *edges[3],uint32_t *prims0,uint32_t *prims1,
int badRefines)
{
//Get Next Free Node
assert(nodeNum == nextFreeNode);
if(nextFreeNode == nAllocedNodes){
int nAlloc = max(2*nAllocedNodes,512);
KdAccelNode *n = AllocAligned<KdAccelNode>(nAlloc);
if(nAllocedNodes > 0){
memcpy(n,nodes,nAllocedNodes*sizeof(KdAccelNode));
FreeAligned(nodes);
}
nodes = n;
nAllocedNodes = nAlloc;
}
++nextFreeNode;
//Initialize leaf Node
if(nPrimitives <= maxPrims || depth == 0){
nodes[nodeNum].initLeaf(primNums,nPrimitives,arena);
return;
}
//Initialize Interior Node
//--Choose split axis
int bestAxis = -1, bestOffset = -1;
float bestCost = INFINITY;
float oldCost = isectCost * float(nPrimitives);
float totalSA = nodeBounds.SurfaceArea();
float invTotalSA = 1.f / totalSA;
Vector d = nodeBounds.pMax - nodeBounds.pMin;
uint32_t axis = nodeBounds.MaximumExtent();
int retries = 0;
retrySplit:
for (int i = 0; i < nPrimitives; ++i) {
int pn = primNums[i];
const BBox &bbox = allPrimBounds[pn];
edges[axis][2*i] = BoundEdge(bbox.pMin[axis], pn, true);
edges[axis][2*i+1] = BoundEdge(bbox.pMax[axis], pn, false);
}
sort(&edges[axis][0], &edges[axis][2*nPrimitives]);
int nBelow = 0, nAbove = nPrimitives;
for (int i = 0; i < 2*nPrimitives; ++i) {
if (edges[axis][i].type == BoundEdge::END) --nAbove;
float edget = edges[axis][i].t;
if (edget > nodeBounds.pMin[axis] &&
edget < nodeBounds.pMax[axis]) {
//Compute cost for split at ith edge
uint32_t otherAxis0 = (axis + 1) % 3, otherAxis1 = (axis + 2) % 3;
float belowSA = 2 * (d[otherAxis0] * d[otherAxis1] +
(edget - nodeBounds.pMin[axis]) *
(d[otherAxis0] + d[otherAxis1]));
float aboveSA = 2 * (d[otherAxis0] * d[otherAxis1] +
(nodeBounds.pMax[axis] - edget) *
(d[otherAxis0] + d[otherAxis1]));
float pBelow = belowSA * invTotalSA;
float pAbove = aboveSA * invTotalSA;
float eb = (nAbove == 0 || nBelow == 0) ? emptyBonus : 0.f;
float cost = traversalCost +
isectCost * (1.f - eb) * (pBelow * nBelow + pAbove * nAbove);
if (cost < bestCost) {
bestCost = cost;
bestAxis = axis;
bestOffset = i;
}
}
if (edges[axis][i].type == BoundEdge::START) ++nBelow;
}
assert(nBelow == nPrimitives && nAbove == 0);
//--Create leaf if np good splits found
if (bestAxis == -1 && retries < 2) {
++retries;
axis = (axis+1) % 3;
goto retrySplit;
}
if (bestCost > oldCost) ++badRefines;
if ((bestCost > 4.f * oldCost && nPrimitives < 16) ||
bestAxis == -1 || badRefines == 3) {
nodes[nodeNum].initLeaf(primNums, nPrimitives, arena);
return;
}
//--Classify primitives with respect to split
int n0 = 0, n1 = 0;
for (int i = 0; i < bestOffset; ++i)
if (edges[bestAxis][i].type == BoundEdge::START)
prims0[n0++] = edges[bestAxis][i].primNum;
for (int i = bestOffset+1; i < 2*nPrimitives; ++i)
if (edges[bestAxis][i].type == BoundEdge::END)
prims1[n1++] = edges[bestAxis][i].primNum;
//--Recursively initialize children nodes
float tsplit = edges[bestAxis][bestOffset].t;
BBox bounds0 = nodeBounds, bounds1 = nodeBounds;
bounds0.pMax[bestAxis] = bounds1.pMin[bestAxis] = tsplit;
buildTree(nodeNum+1, bounds0,
allPrimBounds, prims0, n0, depth-1, edges,
prims0, prims1 + nPrimitives, badRefines);
uint32_t aboveChild = nextFreeNode;
nodes[nodeNum].initInterior(bestAxis, aboveChild, tsplit);
buildTree(aboveChild, bounds1, allPrimBounds, prims1, n1,
depth-1, edges, prims0, prims1 + nPrimitives, badRefines);
}
bool KdTreeAccel::intersect(const Ray& r,float t_min,float t_max,primitive_record &rec) const {
//Compute initial Parametric range of ray inside kd-tree extent
float tMIN,tMAX;
if(!bounds.IntersectP(r,&tMIN,&tMAX))
return false;
//Prepare to traverse kd-tree for ray
Vector invDir(1.f/r.d.x,1.f/r.d.y,1.f/r.d.z);
#define MAX_TODO 64
KdToDo todo[MAX_TODO];
int todoPos = 0;
//Traverse kd-tree nodes in order for ray
bool hit = false;
const KdAccelNode *node = &nodes[0];
while (node != NULL) {
if(t_max < tMIN) break;
if(!node->isLeaf())
{
//Process kd-tree interior node
int axis = node->SplitAxis();
float tplane = (node->SplitPos() - r.o[axis]) * invDir[axis];
const KdAccelNode *firstChild, *secondChild;
int belowFirst = (r.o[axis] < node->SplitPos()) ||
(r.o[axis] == node->SplitPos() && r.d[axis] <= 0);
if (belowFirst) {
firstChild = node + 1;
secondChild = &nodes[node->AboveChild()];
}
else {
firstChild = &nodes[node->AboveChild()];
secondChild = node + 1;
}
if (tplane > tMAX || tplane <= 0)
node = firstChild;
else if (tplane < tMIN)
node = secondChild;
else {
todo[todoPos].node = secondChild;
todo[todoPos].tMIN = tplane;
todo[todoPos].tMAX = tMAX;
++todoPos;
node = firstChild;
tMAX = tplane;
}
}
else
{
//Check for intersections inside leaf node
uint32_t nPrimitives = node->nPrimitives();
if (nPrimitives == 1) {
primitive_record tempRec;
Primitive* prim = primitives[node->onePrimitive];
//Check one prim inside leaf node
if(prim->intersect(r,t_min,t_max,tempRec))
{
rec = tempRec;
hit = true;
}
}
else {
primitive_record tempRec;
float closest_so_far = t_max;
uint32_t *prims = node->primitives;
for (uint32_t i = 0; i < nPrimitives; ++i)
{
//Check one prim inside leaf node
if(primitives[prims[i]]->intersect(r,t_min,closest_so_far,tempRec))
{
hit = true;
closest_so_far = tempRec.t;
rec = tempRec;
}
}
}
//Grab next node to process from todo list
if (todoPos > 0) {
--todoPos;
node = todo[todoPos].node;
tMIN = todo[todoPos].tMIN;
tMAX = todo[todoPos].tMAX;
}
else
break;
}
}
return hit;
}
*CAMERA CODE *
Vector random_in_unit_disk() {
Vector p;
do{
p = 2.f*Vector(drand48(),drand48(),0)-Vector(1.f,1.f,0.f);
}while(Dot(p,p) >= 1.f);
return p;
}
class Camera {
public:
Vector lower_left_corner;
Vector horizontal;
Vector vertical;
Point origin;
Vector u,v,w;
float lens_radius; //Focus
float time0,time1;
Camera(Point lookfrom,Point lookat,Vector vup,
float vfov,float aspect,float aperture,float focus_dist,float t0,float t1){
time0 = t0;
time1 = t1;
lens_radius = aperture/2;
float theta = vfov*M_PI/180.f;
float half_height = tanf(theta/2.f);
float half_width = aspect*half_height;
origin = lookfrom;
w = Normalize(lookfrom - lookat);
u = Normalize(Cross(vup,w));
v = Cross(w,u);
lower_left_corner = toVector(origin) - half_width*focus_dist*u - half_height*focus_dist*v - focus_dist*w;
horizontal = 2*half_width*focus_dist*u;
vertical = 2*half_height*focus_dist*v;
}
Ray get_ray(float s,float t) {
Vector rd = lens_radius*random_in_unit_disk();
Vector offset = u * rd.x + v * rd.y;
float time = time0 + drand48()*(time1-time0);
return Ray(origin + offset,lower_left_corner + s*horizontal + t*vertical - toVector(origin) - offset,time);
}
};

Random generator Rand9() using Rand3()

How can I generate a number between 1 and 9 using a function which generate a number between 1 and 3? The probability to obtain any number between 1 and 9 must be the same, so rand3()+rand3()+rand3() is not a good solution.
Try cartesian-like product:
Rand9() = 3 * (Rand3() - 1) + Rand3()
With 3 * (Rand3() - 1) you make sub-intervals 1-3, 4-6 and 7-9 equally likely. With + Rand3() you will then choose equally on that sub-interval.
Written as a product:
3 * (Rand3() - 1) + Rand3() -> {1, 4, 7} X {+1,+2,+3} -> {1,2,3,4,5,6,7,8,9}
The main idea of the solution is to build 3*3 matrix.
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
function init() {
const rand3 = generateMathRandom(3);
let randFunc = rand3;
const start = 9;
const end = 10;
let i = start;
console.time('---start');
while (i < end) {
randFunc = generateRandom(i, 3, rand3);
healthCheck(i, randFunc);
i++;
}
console.timeEnd('---start');
i = start;
console.time('---start-math');
while (i < end) {
randFunc = generateMathRandom(i);
healthCheck(i, randFunc);
i++;
}
console.timeEnd('---start-math');
}
function generateMathRandom(range) {
return function () {
return Math.floor(Math.random() * range);
}
}
// range - target random range number : e.g 9
// lowerRange - base random range number : e.g 3
// func - function which generate random with the range of lowerRange : e.g rand3
function generateRandom(range, lowerRange, func) {
return function () {
const results = [];
let times = 1;
let matRange = lowerRange;
let mat = Math.sqrt(range);
while(mat > lowerRange) {
mat = Math.sqrt(mat);
times ++;
matRange *= lowerRange;
}
const noneStart = Math.floor(matRange * matRange / range) * range;
for (let i = 0; i < matRange; i++) {
results.push([]);
for (let j = 0; j < matRange; j++) {
const num = i * matRange + j;
if (num < noneStart)
results[i].push(num % range);
else
results[i].push(-1);
}
}
while (true) {
const row = new Array(times).fill(1).map(n => func()).reduce((a, c) => a * lowerRange + c, 0);
const col = new Array(times).fill(1).map(n => func()).reduce((a, c) => a * lowerRange + c, 0);
if (!results[row]) {
debugger;
}
if (results[row][col] == undefined) {
debugger;
}
if (results[row][col] === -1) continue;
return results[row][col];
}
}
}
function healthCheck(range, func = null, count = 100000) {
const funcToCheck = func || rand[range] || null;
if (!funcToCheck) {
console.log('Function is not provided');
return;
}
const health = new Array(range).fill(0);
const checkCount = count - count % range; // To do correct check.
for (let i = 0; i < checkCount; i++) {
health[funcToCheck()]++;
}
const result = health.map((cnt, index) => ({
_value: index,
rate: (cnt / checkCount * 100).toFixed(5)
}));
// console.log('Random result:', result);
let minRate = 100, maxRate = 0;
for (let i = 0; i < range; i++) {
minRate = Math.min(Number(result[i].rate), minRate);
maxRate = Math.max(Number(result[i].rate), maxRate);
}
console.log('Random health<' + range + '>: ' + healthOutput(range, maxRate - minRate));
}
function healthOutput(range, rangeOffset) {
const healthThreshold = 2; // It should be lower for the best Alghorithms
const threshold = healthThreshold;
if (rangeOffset < threshold * 0.2) {
return 'The Super! -> ' + rangeOffset.toFixed(5);
} else if (rangeOffset < threshold * 0.5) {
return 'The Best! --> ' + rangeOffset.toFixed(5);
} else if (rangeOffset < threshold * 1) {
return 'Good work! -> ' + rangeOffset.toFixed(5);
} else if (rangeOffset < threshold * 2) {
return 'Not bad! ---> ' + rangeOffset.toFixed(5);
}
return 'Worst! -----> ' + rangeOffset.toFixed(5);
}
init();

Working Time Calculator c++

Can someone help me? I am creating a program where the user have to input time in and time out per day to compute weekly working hour. The program is directed to accept military time (e.g. 800, 1700, 2030, etc.). There is no error in my code but I have a problem in conversion. If i input 845 for time in and 1600 for time out. The program must display 7.15. Meaning 7 hours and 15 minutes made for that day. But (1600 - 845) / 100 will not work because the answer is 7.55
Here is the program
#include <iostream.h>
int main()
{
int day;
double mHr, tHr, wHr, thHr, fHr;
double in, out, total1;
char holiday;
do
{
switch(day)
{
case 0:
cout<<"Time In for Monday: ";
cin>>in;
cout<<"Enter Time Out for Monday: ";
cin>>out;
if (in<=800)
{
in = 800;
}
if (out>=1700)
{
out = 1700;
}
if ((out-in)<=400)
{
mHr = out - in;
}
else if ((out-in)>=500)
{
mHr = (out - in) - 100;
}
break;
case 1:
cout<<"Enter Time In for Tuesday: ";
cin>>in;
cout<<"Enter Time Out for Tuesday: ";
cin>>out;
if (in<=800)
{
in = 800;
}
if (out>=1700)
{
out = 1700;
}
if ((out-in)<=400)
{
tHr = out - in;
}
else if ((out-in)>=500)
{
tHr = (out - in) - 100;
}
break;
case 2:
cout<<"Enter Time In for Wednesday: ";
cin>>in;
cout<<"Enter Time Out for Wednesday: ";
cin>>out;
if (in<=800)
{
in = 800;
}
if (out>=1700)
{
out = 1700;
}
if ((out-in)<=400)
{
wHr = out - in;
}
else if ((out-in)>=500)
{
wHr = (out - in) - 100;
}
break;
case 3:
cout<<"Enter Time In for Thursday: ";
cin>>in;
cout<<"Enter Time Out for Thursday: ";
cin>>out;
if (in<=800)
{
in = 800;
}
if (out>=1700)
{
out = 1700;
}
if ((out-in)<=400)
{
thHr = out - in;
}
else if ((out-in)>=500)
{
thHr = (out - in) - 100;
}
break;
case 4:
cout<<"Enter Time In for Friday: ";
cin>>in;
cout<<"Enter Time Out for Friday: ";
cin>>out;
if (in<=800)
{
in = 800;
}
if (out>=1700)
{
out = 1700;
}
if ((out-in)<=400)
{
fHr = out - in;
}
else if ((out-in)>=500)
{
fHr = (out - in) - 100;
}
break;
}
day = day + 1;
}
while(day<5);
total1 = (mHr + tHr + wHr + thHr + fHr) / 100;
cout<<"*********************************************************************"<<endl;
cout<<"Weekly Time Record:"<<endl;
cout<<" The total number of working hours for regular hours: "<<total1<<" Hrs."<<endl;
cout<<"*********************************************************************"<<endl;
return 0;
}
Easiest way is probably to convert each input time to the number of minutes elapsed since midnight, and then subtract the two:
double calculateHours(int militaryStartTime, int militaryEndTime)
{
int startHours = militaryStartTime / 100;
int startMinutes = militaryStartTime % 100;
int startTime = startHours * 60 + startMinutes; // minutes since midnight
int endHours = militaryEndTime / 100;
int endMinutes = militaryEndTime % 100;
int endTime = endHours * 60 + endMinutes; // minutes since midnight
return (endTime - startTime) / 60.0;
}

Resources