aboutsummaryrefslogtreecommitdiff
path: root/src/sfml/system
diff options
context:
space:
mode:
Diffstat (limited to 'src/sfml/system')
-rw-r--r--src/sfml/system/Clock.zig59
-rw-r--r--src/sfml/system/Time.zig114
-rw-r--r--src/sfml/system/vector.zig104
3 files changed, 277 insertions, 0 deletions
diff --git a/src/sfml/system/Clock.zig b/src/sfml/system/Clock.zig
new file mode 100644
index 0000000..17b6e5b
--- /dev/null
+++ b/src/sfml/system/Clock.zig
@@ -0,0 +1,59 @@
+//! Utility class that measures the elapsed time.
+
+const sf = struct {
+ pub usingnamespace @import("../sfml.zig");
+ pub usingnamespace system;
+ pub usingnamespace graphics;
+};
+
+const Clock = @This();
+
+// Constructor/destructor
+
+/// Inits a clock. The clock will have its time set at 0 at this point, and automatically starts
+/// Std.time timer also is a good alternative
+pub fn create() !Clock {
+ var clock = sf.c.sfClock_create();
+ if (clock == null)
+ return sf.Error.nullptrUnknownReason;
+
+ return Clock{ .ptr = clock.? };
+}
+
+/// Destroys this clock
+pub fn destroy(self: Clock) void {
+ sf.c.sfClock_destroy(self.ptr);
+}
+
+// Clock control
+/// Gets the elapsed seconds
+pub fn getElapsedTime(self: Clock) sf.Time {
+ var time = sf.c.sfClock_getElapsedTime(self.ptr).microseconds;
+ return sf.Time{ .us = time };
+}
+
+/// Gets the elapsed seconds and restarts the timer
+pub fn restart(self: Clock) sf.Time {
+ var time = sf.c.sfClock_restart(self.ptr).microseconds;
+ return sf.Time{ .us = time };
+}
+
+/// Pointer to the csfml structure
+ptr: *sf.c.sfClock,
+
+test "clock: sleep test" {
+ const tst = @import("std").testing;
+
+ // This tests just sleeps and check what the timer measured (not very accurate but eh)
+ var clk = try Clock.create();
+ defer clk.destroy();
+
+ sf.Time.milliseconds(500).sleep();
+
+ try tst.expectApproxEqAbs(@as(f32, 0.5), clk.getElapsedTime().asSeconds(), 0.1);
+
+ sf.Time.sleep(sf.Time.seconds(0.2));
+
+ try tst.expectApproxEqAbs(@as(f32, 0.7), clk.restart().asSeconds(), 0.1);
+ try tst.expectApproxEqAbs(@as(f32, 0), clk.getElapsedTime().asSeconds(), 0.01);
+}
diff --git a/src/sfml/system/Time.zig b/src/sfml/system/Time.zig
new file mode 100644
index 0000000..2e8a34c
--- /dev/null
+++ b/src/sfml/system/Time.zig
@@ -0,0 +1,114 @@
+//! Represents a time value.
+
+const sf = @import("../sfml.zig");
+
+const Time = @This();
+
+// Constructors
+
+/// Converts a time from a csfml object
+/// For inner workings
+pub fn fromCSFML(time: sf.c.sfTime) Time {
+ return Time{ .us = time.microseconds };
+}
+
+/// Converts a time to a csfml object
+/// For inner workings
+pub fn toCSFML(self: Time) sf.c.sfTime {
+ return sf.c.sfTime{ .microseconds = self.us };
+}
+
+/// Creates a time object from a seconds count
+pub fn seconds(s: f32) Time {
+ return Time{ .us = @floatToInt(i64, s * 1_000) * 1_000 };
+}
+
+/// Creates a time object from milliseconds
+pub fn milliseconds(ms: i32) Time {
+ return Time{ .us = @intCast(i64, ms) * 1_000 };
+}
+
+/// Creates a time object from microseconds
+pub fn microseconds(us: i64) Time {
+ return Time{ .us = us };
+}
+
+// Getters
+
+/// Gets this time measurement as microseconds
+pub fn asMicroseconds(self: Time) i64 {
+ return self.us;
+}
+
+/// Gets this time measurement as milliseconds
+pub fn asMilliseconds(self: Time) i32 {
+ return @truncate(i32, @divFloor(self.us, 1_000));
+}
+
+/// Gets this time measurement as seconds (as a float)
+pub fn asSeconds(self: Time) f32 {
+ return @intToFloat(f32, self.us) / 1_000_000;
+}
+
+// Misc
+
+/// Sleeps the amount of time specified
+pub fn sleep(time: Time) void {
+ sf.c.sfSleep(time.toCSFML());
+}
+
+/// A time of zero
+pub const Zero = microseconds(0);
+
+us: i64,
+
+pub const TimeSpan = struct {
+ // Constructors
+
+ /// Construcs a time span
+ pub fn init(begin: Time, length: Time) TimeSpan {
+ return TimeSpan{
+ .offset = begin,
+ .length = length,
+ };
+ }
+
+ /// Converts a timespan from a csfml object
+ /// For inner workings
+ pub fn fromCSFML(span: sf.c.sfTimeSpan) TimeSpan {
+ return TimeSpan{
+ .offset = Time.fromCSFML(span.offset),
+ .length = Time.fromCSFML(span.length),
+ };
+ }
+
+ /// Converts a timespan to a csfml object
+ /// For inner workings
+ pub fn toCSFML(self: TimeSpan) sf.c.sfTimeSpan {
+ return sf.c.sfTimeSpan{
+ .offset = self.offset.toCSFML(),
+ .length = self.length.toCSFML(),
+ };
+ }
+
+ /// The beginning of this span
+ offset: Time,
+ /// The length of this time span
+ length: Time,
+};
+
+test "time: conversion" {
+ const tst = @import("std").testing;
+
+ var t = Time.microseconds(5_120_000);
+
+ try tst.expectEqual(@as(i32, 5_120), t.asMilliseconds());
+ try tst.expectApproxEqAbs(@as(f32, 5.12), t.asSeconds(), 0.0001);
+
+ t = Time.seconds(12);
+
+ try tst.expectApproxEqAbs(@as(f32, 12), t.asSeconds(), 0.0001);
+
+ t = Time.microseconds(800);
+ try tst.expectApproxEqAbs(@as(f32, 0.0008), t.asSeconds(), 0.0001);
+}
diff --git a/src/sfml/system/vector.zig b/src/sfml/system/vector.zig
new file mode 100644
index 0000000..7e3e500
--- /dev/null
+++ b/src/sfml/system/vector.zig
@@ -0,0 +1,104 @@
+//! Utility struct for manipulating 2-dimensional vectors.
+
+const sf = @import("../sfml_import.zig");
+
+pub fn Vector2(comptime T: type) type {
+ return packed struct {
+ const Self = @This();
+
+ /// The CSFML vector type equivalent
+ const CsfmlEquivalent = switch (T) {
+ c_uint => sf.c.sfVector2u,
+ c_int => sf.c.sfVector2i,
+ f32 => sf.c.sfVector2f,
+ else => void,
+ };
+
+ /// Makes a CSFML vector with this vector (only if the corresponding type exists)
+ /// This is mainly for the inner workings of this wrapper
+ pub fn toCSFML(self: Self) CsfmlEquivalent {
+ if (CsfmlEquivalent == void) @compileError("This vector type doesn't have a CSFML equivalent.");
+ return @bitCast(CsfmlEquivalent, self);
+ }
+
+ /// Creates a vector from a CSFML one (only if the corresponding type exists)
+ /// This is mainly for the inner workings of this wrapper
+ pub fn fromCSFML(vec: CsfmlEquivalent) Self {
+ if (CsfmlEquivalent == void) @compileError("This vector type doesn't have a CSFML equivalent.");
+ return @bitCast(Self, vec);
+ }
+
+ /// Adds two vectors
+ pub fn add(self: Self, other: Self) Self {
+ return Self{ .x = self.x + other.x, .y = self.y + other.y };
+ }
+
+ /// Substracts two vectors
+ pub fn substract(self: Self, other: Self) Self {
+ return Self{ .x = self.x - other.x, .y = self.y - other.y };
+ }
+
+ /// Scales a vector
+ pub fn scale(self: Self, scalar: T) Self {
+ return Self{ .x = self.x * scalar, .y = self.y * scalar };
+ }
+
+ /// x component of the vector
+ x: T,
+ /// y component of the vector
+ y: T
+ };
+}
+
+pub const Vector3f = struct {
+ const Self = @This();
+
+ /// Makes a CSFML vector with this vector (only if the corresponding type exists)
+ /// This is mainly for the inner workings of this wrapper
+ pub fn toCSFML(self: Self) sf.c.sfVector3f {
+ return @bitCast(sf.c.sfVector3f, self);
+ }
+
+ /// Creates a vector from a CSFML one (only if the corresponding type exists)
+ /// This is mainly for the inner workings of this wrapper
+ pub fn fromCSFML(vec: sf.c.sfVector3f) Self {
+ return @bitCast(Self, vec);
+ }
+
+ /// x component of the vector
+ x: f32,
+ /// y component of the vector
+ y: f32,
+ /// z component of the vector
+ z: f32,
+};
+
+test "vector: sane from/to CSFML vectors" {
+ const tst = @import("std").testing;
+
+ inline for ([_]type{ c_int, c_uint, f32 }) |T| {
+ const VecT = Vector2(T);
+ const vec = VecT{ .x = 1, .y = 3 };
+ const cvec = vec.toCSFML();
+
+ try tst.expectEqual(vec.x, cvec.x);
+ try tst.expectEqual(vec.y, cvec.y);
+
+ const vec2 = VecT.fromCSFML(cvec);
+
+ try tst.expectEqual(vec, vec2);
+ }
+
+ {
+ const vec = Vector3f{ .x = 1, .y = 3.5, .z = -12 };
+ const cvec = vec.toCSFML();
+
+ try tst.expectEqual(vec.x, cvec.x);
+ try tst.expectEqual(vec.y, cvec.y);
+ try tst.expectEqual(vec.z, cvec.z);
+
+ const vec2 = Vector3f.fromCSFML(cvec);
+
+ try tst.expectEqual(vec, vec2);
+ }
+}