Gondwana Game Engine Development (master) - 2.6.1
Gondwana is a cross-platform 2.5D game and rendering engine written in C#/.NET 8. It provides fine-grained control over rendering, timing, and scene composition, with built-in support for parallax, z-ordering, pixel overhang, collision detection, and particle effects. Gondwana targets desktop and web platforms using SkiaSharp for graphics and pluggable audio backends for desktop and browser targets.
Loading...
Searching...
No Matches
Sprite.Resize.cs
1using System.Drawing;
3
5
9public partial class Sprite
10{
14 public event Action? ResizeComplete;
15
16 private bool _isResizing;
17 private float _resizeElapsedSeconds;
18 private float _resizeDurationSeconds;
19 private Size _resizeStart;
20 private Size _resizeTarget;
21
22 private bool _resizeReturnToStart;
23 private float _resizeReturnDurationSeconds;
24 private Size _resizeOriginalStart;
25 private Size _resizePeak;
26
27 private bool _isPulseMode;
28 private bool _pulseLoop;
29 private bool _pulseForward;
30 private float _pulseGrowDurationSeconds;
31 private float _pulseShrinkDurationSeconds;
32
33 private CollisionAdjust _resizeStartCollisionAdjust;
34 private Size _resizeStartSizeForCollision;
35
36 internal void AdvanceResize(float deltaSeconds)
37 {
38 if (!_isResizing)
39 return;
40
41 if (_resizeDurationSeconds <= 0f)
42 {
43 RenderSize = _resizeTarget;
44 ApplyScaledCollisionAdjust(RenderSize);
45 CompleteResizeLeg();
46 return;
47 }
48
49 _resizeElapsedSeconds += deltaSeconds;
50
51 float t = _resizeElapsedSeconds / _resizeDurationSeconds;
52 if (t >= 1f)
53 t = 1f;
54
55 int w = (int)MathF.Round(
56 _resizeStart.Width + ((_resizeTarget.Width - _resizeStart.Width) * t));
57 int h = (int)MathF.Round(
58 _resizeStart.Height + ((_resizeTarget.Height - _resizeStart.Height) * t));
59
60 var next = new Size(Math.Max(1, w), Math.Max(1, h));
61
62 if (next != _renderSize)
63 {
64 RenderSize = next;
65 ApplyScaledCollisionAdjust(next);
66 }
67
68 if (t >= 1f)
69 CompleteResizeLeg();
70 }
71
72 private void CompleteResizeLeg()
73 {
74 RenderSize = _resizeTarget;
75 ApplyScaledCollisionAdjust(RenderSize);
76
77 if (_isPulseMode)
78 {
79 if (_pulseForward)
80 {
81 _pulseForward = false;
82 StartResizeLeg(
83 start: _resizePeak,
84 target: _resizeOriginalStart,
85 durationSeconds: _pulseShrinkDurationSeconds,
86 returnToStart: false,
87 returnDurationSeconds: 0f);
88 return;
89 }
90
91 if (_pulseLoop)
92 {
93 _pulseForward = true;
94 StartResizeLeg(
95 start: _resizeOriginalStart,
96 target: _resizePeak,
97 durationSeconds: _pulseGrowDurationSeconds,
98 returnToStart: false,
99 returnDurationSeconds: 0f);
100 return;
101 }
102
103 _isPulseMode = false;
104 _isResizing = false;
105 ResizeComplete?.Invoke();
106 return;
107 }
108
109 if (_resizeReturnToStart)
110 {
111 StartResizeLeg(
112 start: RenderSize,
113 target: _resizeOriginalStart,
114 durationSeconds: _resizeReturnDurationSeconds,
115 returnToStart: false,
116 returnDurationSeconds: 0f);
117 }
118 else
119 {
120 _isResizing = false;
121 ResizeComplete?.Invoke();
122 }
123 }
124
125 private void StartResizeLeg(
126 Size start,
127 Size target,
128 float durationSeconds,
129 bool returnToStart,
130 float returnDurationSeconds)
131 {
132 _resizeStart = start;
133 _resizeTarget = target;
134 _resizeDurationSeconds = Math.Max(0f, durationSeconds);
135 _resizeElapsedSeconds = 0f;
136 _isResizing = true;
137
138 _resizeReturnToStart = returnToStart;
139 _resizeReturnDurationSeconds = Math.Max(0f, returnDurationSeconds);
140
141 _resizeStartCollisionAdjust = AdjustCollisionArea;
142 _resizeStartSizeForCollision = start;
143 }
144
145 private void ApplyScaledCollisionAdjust(Size currentSize)
146 {
147 if (_resizeStartSizeForCollision.Width <= 0 ||
148 _resizeStartSizeForCollision.Height <= 0)
149 {
150 return;
151 }
152
153 float sx = (float)currentSize.Width / _resizeStartSizeForCollision.Width;
154 float sy = (float)currentSize.Height / _resizeStartSizeForCollision.Height;
155
156 AdjustCollisionArea = new CollisionAdjust(
157 top: (int)MathF.Round(_resizeStartCollisionAdjust.Top * sy),
158 bottom: (int)MathF.Round(_resizeStartCollisionAdjust.Bottom * sy),
159 left: (int)MathF.Round(_resizeStartCollisionAdjust.Left * sx),
160 right: (int)MathF.Round(_resizeStartCollisionAdjust.Right * sx));
161 }
162
168 public void ResizeTo(Size targetSize, float durationSeconds)
169 {
170 targetSize = new Size(
171 Math.Max(1, targetSize.Width),
172 Math.Max(1, targetSize.Height));
173
174 _isPulseMode = false;
175 _pulseLoop = false;
176 _resizeOriginalStart = RenderSize;
177
178 StartResizeLeg(
179 start: RenderSize,
180 target: targetSize,
181 durationSeconds: durationSeconds,
182 returnToStart: false,
183 returnDurationSeconds: 0f);
184 }
185
191 public void ScaleBy(float factor, float durationSeconds)
192 {
193 factor = MathF.Max(0.01f, factor);
194
195 int w = (int)MathF.Round(RenderSize.Width * factor);
196 int h = (int)MathF.Round(RenderSize.Height * factor);
197
198 ResizeTo(
199 new Size(Math.Max(1, w), Math.Max(1, h)),
200 durationSeconds);
201 }
202
210 public void PulseTo(
211 Size targetSize,
212 float growDurationSeconds,
213 float shrinkDurationSeconds,
214 bool loop = false)
215 {
216 targetSize = new Size(
217 Math.Max(1, targetSize.Width),
218 Math.Max(1, targetSize.Height));
219
220 _resizeOriginalStart = RenderSize;
221 _resizePeak = targetSize;
222
223 _isPulseMode = true;
224 _pulseLoop = loop;
225 _pulseForward = true;
226 _pulseGrowDurationSeconds = Math.Max(0f, growDurationSeconds);
227 _pulseShrinkDurationSeconds = Math.Max(0f, shrinkDurationSeconds);
228
229 StartResizeLeg(
230 start: _resizeOriginalStart,
231 target: _resizePeak,
232 durationSeconds: _pulseGrowDurationSeconds,
233 returnToStart: false,
234 returnDurationSeconds: 0f);
235 }
236
244 public void PulseBy(
245 float factor,
246 float growDurationSeconds,
247 float shrinkDurationSeconds,
248 bool loop = false)
249 {
250 factor = MathF.Max(0.01f, factor);
251
252 int w = (int)MathF.Round(RenderSize.Width * factor);
253 int h = (int)MathF.Round(RenderSize.Height * factor);
254
255 PulseTo(
256 new Size(Math.Max(1, w), Math.Max(1, h)),
257 growDurationSeconds,
258 shrinkDurationSeconds,
259 loop);
260 }
261
267 public void StopPulse(bool snapBack = true, float returnDuration = 0f)
268 {
269 Size originalSize = _resizeOriginalStart;
270 var originalCollisionAdjust = _resizeStartCollisionAdjust;
271
272 CancelResize();
273
274 if (!snapBack)
275 return;
276
277 if (returnDuration <= 0f)
278 {
279 RenderSize = originalSize;
280 AdjustCollisionArea = originalCollisionAdjust;
281 }
282 else
283 {
284 ResizeTo(originalSize, returnDuration);
285 }
286 }
287
291 public void CancelResize()
292 {
293 _isResizing = false;
294 _resizeReturnToStart = false;
295 _isPulseMode = false;
296 _pulseLoop = false;
297 _pulseForward = false;
298
299 ResizeComplete?.Invoke();
300 }
301}
Represents a movable visual element on a scene layer.
Definition Sprite.cs:20
void PulseBy(float factor, float growDurationSeconds, float shrinkDurationSeconds, bool loop=false)
Pulses by a factor relative to the current render size.
void ResizeTo(Size targetSize, float durationSeconds)
Smoothly resizes the sprite to an absolute pixel size.
Size RenderSize
Gets or sets the render size.
Definition Sprite.cs:559
void ScaleBy(float factor, float durationSeconds)
Scales the sprite by a factor relative to its current render size.
void PulseTo(Size targetSize, float growDurationSeconds, float shrinkDurationSeconds, bool loop=false)
Resizes to an absolute target size and then returns to the original size.
void CancelResize()
Cancels any in-progress resize or pulse.
void StopPulse(bool snapBack=true, float returnDuration=0f)
Stops the current pulse, optionally returning to the original size.
Action? ResizeComplete
Raised when a resize or pulse animation completes its current leg, or when cancelled.
virtual CollisionAdjust AdjustCollisionArea
Gets or sets the collision adjustment used to derive CollisionArea.
Definition Tile.cs:285
Per-edge inset amounts applied to visual bounds to produce a collision rectangle.