Skip to content

Commit 33faf52

Browse files
Merge pull request #43 from ArtifactForms/working2
Working2
2 parents 0c58cfc + 41b2e22 commit 33faf52

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+6214
-2003
lines changed

src/main/java/engine/Timer.java

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
package engine;
2+
3+
/**
4+
* The {@code Timer} class provides a utility for tracking elapsed time, frames per second (FPS),
5+
* and time scaling for games or applications. It uses nanosecond precision for timekeeping and
6+
* offers features such as formatted time representation, time-per-frame calculation, and
7+
* slow-motion or speed-up effects via time scaling.
8+
*
9+
* <p>Key features include:
10+
*
11+
* <ul>
12+
* <li>Tracking total elapsed time (scaled and unscaled).
13+
* <li>Calculating frames per second (FPS).
14+
* <li>Formatting time as hours:minutes:seconds.
15+
* <li>Adjustable time scaling for slow-motion or fast-forward effects.
16+
* </ul>
17+
*
18+
* This class is designed to be updated on every frame of an application or game.
19+
*/
20+
public class Timer {
21+
22+
/** Real world time when the timer started. */
23+
private long startTime;
24+
25+
/** The last recorded time in nanoseconds. */
26+
private long lastTime;
27+
28+
/** The time in milliseconds taken for the last frame. */
29+
private float time;
30+
31+
/** Accumulates milliseconds for FPS calculation. */
32+
private long millisecondCounter;
33+
34+
/** The frame count during the last FPS update. */
35+
private int lastFrameCount;
36+
37+
/** The calculated frames per second (FPS). */
38+
private int fps;
39+
40+
/** Total elapsed time in milliseconds. */
41+
private long totalTime;
42+
43+
/** Scaling factor for time (default is 1.0 for real-time). */
44+
private float timeScale;
45+
46+
/** Total number of frames since the Timer started. */
47+
private int frameCount;
48+
49+
/** Constructs a {@code Timer} with a default time scale of 1.0. */
50+
public Timer() {
51+
this.startTime = System.nanoTime();
52+
this.lastTime = System.nanoTime();
53+
this.time = 0;
54+
this.totalTime = 0;
55+
this.timeScale = 1f;
56+
this.frameCount = 0;
57+
}
58+
59+
/**
60+
* Constructs a {@code Timer} with the specified initial time scale.
61+
*
62+
* @param initialTimeScale the initial time scaling factor
63+
*/
64+
public Timer(float initialTimeScale) {
65+
this.timeScale = initialTimeScale;
66+
}
67+
68+
/**
69+
* Returns the current frames per second (FPS).
70+
*
71+
* @return the frames per second
72+
*/
73+
public float getFrameRate() {
74+
return fps;
75+
}
76+
77+
/** Updates the FPS calculation based on the accumulated milliseconds. */
78+
private void updateFPS() {
79+
millisecondCounter += time;
80+
if (millisecondCounter >= 1000) {
81+
millisecondCounter = 0;
82+
fps = frameCount - lastFrameCount;
83+
lastFrameCount = frameCount;
84+
}
85+
}
86+
87+
/**
88+
* Updates the Timer. This method must be called once per frame to ensure accurate time tracking.
89+
*/
90+
public void update() {
91+
long currentTime = System.nanoTime();
92+
time = (currentTime - lastTime) / 1_000_000.0f; // Convert to milliseconds
93+
lastTime = currentTime;
94+
totalTime += time;
95+
frameCount++;
96+
updateFPS();
97+
}
98+
99+
/**
100+
* Resets the {@code Timer} to its initial state, clearing all accumulated time and frame count
101+
* values. This includes resetting the following:
102+
*
103+
* <ul>
104+
* <li>The start time to the current system time.
105+
* <li>The last time recorded to the current system time.
106+
* <li>The total elapsed time to zero.
107+
* <li>The frame count to zero.
108+
* <li>The frames per second (FPS) to zero.
109+
* <li>The millisecond counter to zero.
110+
* <li>The last frame count for FPS calculation to zero.
111+
* </ul>
112+
*
113+
* <p>This method can be used when you need to restart the timer, such as for restarting the game
114+
* / application or resetting the simulation state.
115+
*/
116+
public void reset() {
117+
this.startTime = System.nanoTime();
118+
this.lastTime = startTime;
119+
this.time = 0;
120+
this.totalTime = 0;
121+
this.frameCount = 0;
122+
this.fps = 0;
123+
this.millisecondCounter = 0;
124+
this.lastFrameCount = 0;
125+
}
126+
127+
/**
128+
* Returns the total elapsed time in seconds, scaled by the current time scale.
129+
*
130+
* @return the scaled total elapsed time in seconds
131+
*/
132+
public float getTotalTime() {
133+
return totalTime / 1000.0f * timeScale;
134+
}
135+
136+
/**
137+
* Returns the total elapsed time in seconds, independent of the time scale.
138+
*
139+
* @return the unscaled total elapsed time in seconds
140+
*/
141+
public float getUnscaledTotalTime() {
142+
return totalTime / 1000.0f;
143+
}
144+
145+
/**
146+
* Returns a formatted string representing the scaled total time in the format HH:MM:SS.
147+
*
148+
* @return the formatted scaled total time
149+
*/
150+
public String getFormattedTotalTime() {
151+
return formatTime(getTotalTime());
152+
}
153+
154+
/**
155+
* Returns a formatted string representing the unscaled total time in the format HH:MM:SS.
156+
*
157+
* @return the formatted unscaled total time
158+
*/
159+
public String getUnscaledFormattedTotalTime() {
160+
return formatTime(getUnscaledTotalTime());
161+
}
162+
163+
/**
164+
* Returns the time it took to complete the last frame in seconds, scaled by the current time
165+
* scale.
166+
*
167+
* @return the scaled time per frame in seconds
168+
*/
169+
public float getTimePerFrame() {
170+
return time / 1000.0f * timeScale;
171+
}
172+
173+
/**
174+
* Returns the time it took to complete the last frame in seconds, independent of the time scale.
175+
*
176+
* @return the unscaled time per frame in seconds
177+
*/
178+
public float getUnscaledTimePerFrame() {
179+
return time / 1000.0f;
180+
}
181+
182+
/**
183+
* Returns the current time scaling factor.
184+
*
185+
* @return the time scale
186+
*/
187+
public float getTimeScale() {
188+
return timeScale;
189+
}
190+
191+
/**
192+
* Sets the time scaling factor. A value of 1.0 represents real-time, values less than 1.0 slow
193+
* down time, and values greater than 1.0 speed up time.
194+
*
195+
* @param timeScale the new time scaling factor
196+
*/
197+
public void setTimeScale(float timeScale) {
198+
this.timeScale = timeScale;
199+
}
200+
201+
/**
202+
* Returns the real-time elapsed since the game / application started, measured in seconds.
203+
*
204+
* <p>This method uses `System.nanoTime()` to obtain a high-precision timestamp. The returned
205+
* value is a `float` representing the elapsed time in seconds.
206+
*
207+
* @return The real-time elapsed since the game started, in seconds.
208+
*/
209+
public float getRealtimeSinceStartup() {
210+
return (System.nanoTime() - startTime) / 1_000_000_000.0f;
211+
}
212+
213+
/**
214+
* Returns the real-time elapsed since the game / application started, measured in seconds, as a
215+
* `double` value.
216+
*
217+
* <p>This method uses `System.nanoTime()` to obtain a high-precision timestamp. The returned
218+
* value is a `double` representing the elapsed time in seconds, providing higher precision than
219+
* the `float` version.
220+
*
221+
* @return The real-time elapsed since the game started, in seconds, as a `double`.
222+
*/
223+
public double getRealtimeSinceStartupAsDouble() {
224+
return (System.nanoTime() - startTime) / 1_000_000_000.0;
225+
}
226+
227+
/**
228+
* Returns the total number of frames that have passed since the Timer started.
229+
*
230+
* @return the total frame count
231+
*/
232+
public int getFrameCount() {
233+
return frameCount;
234+
}
235+
236+
/**
237+
* Formats a time value in seconds into a string in the format HH:MM:SS.
238+
*
239+
* @param timeInSeconds the time in seconds to format
240+
* @return the formatted time string
241+
*/
242+
private String formatTime(float timeInSeconds) {
243+
int s = (int) timeInSeconds;
244+
return String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, s % 60);
245+
}
246+
247+
/**
248+
* Returns a string representation of this Timer, showing its current state.
249+
*
250+
* @return a string representation of the Timer
251+
*/
252+
@Override
253+
public String toString() {
254+
return "Timer [millisecondCounter="
255+
+ millisecondCounter
256+
+ ", lastFrameCount="
257+
+ lastFrameCount
258+
+ ", fps="
259+
+ fps
260+
+ ", lastTime="
261+
+ lastTime
262+
+ ", time="
263+
+ time
264+
+ ", totalTime="
265+
+ totalTime
266+
+ ", timeScale="
267+
+ timeScale
268+
+ ", frameCount="
269+
+ frameCount
270+
+ "]";
271+
}
272+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package engine.components;
2+
3+
import engine.scene.SceneNode;
4+
5+
/**
6+
* Abstract base class for all components in the scene graph.
7+
* <p>
8+
* This class provides a shared implementation of common functionality across
9+
* all components, reducing boilerplate and centralizing shared logic for ease
10+
* of maintenance.
11+
* </p>
12+
*/
13+
public abstract class AbstractComponent implements Component {
14+
15+
/** Reference to the owning SceneNode */
16+
protected SceneNode owner;
17+
18+
/**
19+
* Sets the owner (parent node) of this component.
20+
* <p>
21+
* This is common logic provided by the abstract class to ensure consistency
22+
* among all components.
23+
* </p>
24+
*
25+
* @param owner The SceneNode that owns this component.
26+
*/
27+
@Override
28+
public void setOwner(SceneNode owner) {
29+
this.owner = owner;
30+
}
31+
32+
/**
33+
* Retrieves the owning node for convenience.
34+
*
35+
* @return The owning SceneNode instance.
36+
*/
37+
public SceneNode getOwner() {
38+
return owner;
39+
}
40+
41+
}

0 commit comments

Comments
 (0)