414 lines
15 KiB
HTML
414 lines
15 KiB
HTML
|
||
|
||
|
||
<!DOCTYPE html>
|
||
<html id="htmlId">
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||
<title>Coverage Report > FireParticleSystem</title>
|
||
<style type="text/css">
|
||
@import "../../css/coverage.css";
|
||
@import "../../css/idea.min.css";
|
||
</style>
|
||
<script type="text/javascript" src="../../js/highlight.min.js"></script>
|
||
<script type="text/javascript" src="../../js/highlightjs-line-numbers.min.js"></script>
|
||
</head>
|
||
|
||
<body>
|
||
<div class="content">
|
||
<div class="breadCrumbs">
|
||
Current scope: <a href="../../index.html">all classes</a>
|
||
<span class="separator">|</span>
|
||
<a href="../index.html">it.polimi.ingsw.gc14.View.GUI</a>
|
||
</div>
|
||
|
||
<h1>Coverage Summary for Class: FireParticleSystem (it.polimi.ingsw.gc14.View.GUI)</h1>
|
||
|
||
<table class="coverageStats">
|
||
|
||
<tr>
|
||
<th class="name">Class</th>
|
||
<th class="coverageStat
|
||
">
|
||
Method, %
|
||
</th>
|
||
<th class="coverageStat
|
||
">
|
||
Branch, %
|
||
</th>
|
||
<th class="coverageStat
|
||
">
|
||
Line, %
|
||
</th>
|
||
</tr>
|
||
<tr>
|
||
<td class="name">FireParticleSystem</td>
|
||
<td class="coverageStat">
|
||
<span class="percent">
|
||
0%
|
||
</span>
|
||
<span class="absValue">
|
||
(0/6)
|
||
</span>
|
||
</td>
|
||
<td class="coverageStat">
|
||
<span class="percent">
|
||
0%
|
||
</span>
|
||
<span class="absValue">
|
||
(0/31)
|
||
</span>
|
||
</td>
|
||
<td class="coverageStat">
|
||
<span class="percent">
|
||
0%
|
||
</span>
|
||
<span class="absValue">
|
||
(0/50)
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="name">FireParticleSystem$1</td>
|
||
<td class="coverageStat">
|
||
<span class="percent">
|
||
0%
|
||
</span>
|
||
<span class="absValue">
|
||
(0/2)
|
||
</span>
|
||
</td>
|
||
<td class="coverageStat">
|
||
<span class="percent">
|
||
0%
|
||
</span>
|
||
<span class="absValue">
|
||
(0/2)
|
||
</span>
|
||
</td>
|
||
<td class="coverageStat">
|
||
<span class="percent">
|
||
0%
|
||
</span>
|
||
<span class="absValue">
|
||
(0/4)
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="name">FireParticleSystem$Particle</td>
|
||
<td class="coverageStat">
|
||
<span class="percent">
|
||
0%
|
||
</span>
|
||
<span class="absValue">
|
||
(0/7)
|
||
</span>
|
||
</td>
|
||
<td class="coverageStat">
|
||
<span class="percent">
|
||
0%
|
||
</span>
|
||
<span class="absValue">
|
||
(0/40)
|
||
</span>
|
||
</td>
|
||
<td class="coverageStat">
|
||
<span class="percent">
|
||
0%
|
||
</span>
|
||
<span class="absValue">
|
||
(0/69)
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="name"><strong>Total</strong></td>
|
||
<td class="coverageStat">
|
||
<span class="percent">
|
||
0%
|
||
</span>
|
||
<span class="absValue">
|
||
(0/15)
|
||
</span>
|
||
</td>
|
||
<td class="coverageStat">
|
||
<span class="percent">
|
||
0%
|
||
</span>
|
||
<span class="absValue">
|
||
(0/73)
|
||
</span>
|
||
</td>
|
||
<td class="coverageStat">
|
||
<span class="percent">
|
||
0%
|
||
</span>
|
||
<span class="absValue">
|
||
(0/123)
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<br/>
|
||
<br/>
|
||
|
||
|
||
<pre>
|
||
<code class="sourceCode" id="sourceCode"> package it.polimi.ingsw.gc14.View.GUI;
|
||
|
||
import javafx.animation.AnimationTimer;
|
||
import javafx.scene.Scene;
|
||
import javafx.scene.layout.Pane;
|
||
import javafx.scene.paint.Color;
|
||
import javafx.scene.shape.Circle;
|
||
|
||
import java.util.ArrayList;
|
||
import java.util.Iterator;
|
||
import java.util.List;
|
||
import java.util.Random;
|
||
|
||
//TODO ALL JAVADOC
|
||
public class FireParticleSystem {
|
||
|
||
private static final int MAX_PARTICLES = 30;
|
||
private static final long SPAWN_INTERVAL_NS = 100_000_000L;
|
||
private static final long FRAME_INTERVAL_NS = 1_000_000_000L / 30; // 30 fps cap
|
||
private static final int STEPS_PER_FRAME = 3; // physics steps per frame → 3× speed
|
||
|
||
private final Pane pane;
|
||
private final Scene scene;
|
||
<b class="nc"> private final List<Particle> particles = new ArrayList<>();</b>
|
||
<b class="nc"> private final Random rnd = new Random();</b>
|
||
private AnimationTimer timer;
|
||
<b class="nc"> private long lastSpawn = 0;</b>
|
||
<b class="nc"> private long lastFrame = 0;</b>
|
||
<b class="nc"> private boolean warmedUp = false;</b>
|
||
|
||
<b class="nc"> public FireParticleSystem(Scene scene) {</b>
|
||
<b class="nc"> this.scene = scene;</b>
|
||
<b class="nc"> pane = new Pane();</b>
|
||
<b class="nc"> pane.setMouseTransparent(true);</b>
|
||
<b class="nc"> pane.setPickOnBounds(false);</b>
|
||
}
|
||
|
||
/** Returns the transparent overlay pane that holds all particle nodes. */
|
||
<b class="nc"> public Pane getPane() { return pane; }</b>
|
||
|
||
/** Starts the animation timer. */
|
||
public void start() {
|
||
<b class="nc"> timer = new AnimationTimer() {</b>
|
||
@Override
|
||
public void handle(long now) {
|
||
<b class="nc"> if (now - lastFrame < FRAME_INTERVAL_NS) return;</b>
|
||
<b class="nc"> lastFrame = now;</b>
|
||
<b class="nc"> tick(now);</b>
|
||
}
|
||
};
|
||
<b class="nc"> timer.start();</b>
|
||
}
|
||
|
||
/** Stops the animation timer. */
|
||
public void stop() {
|
||
<b class="nc"> if (timer != null) timer.stop();</b>
|
||
}
|
||
|
||
private void tick(long now) {
|
||
<b class="nc"> double w = scene.getWidth();</b>
|
||
<b class="nc"> double h = scene.getHeight();</b>
|
||
<b class="nc"> if (w == 0 || h == 0) return;</b>
|
||
|
||
<b class="nc"> if (!warmedUp) {</b>
|
||
<b class="nc"> warmedUp = true;</b>
|
||
<b class="nc"> for (int i = 0; i < MAX_PARTICLES; i++) {</b>
|
||
<b class="nc"> Particle p = spawnParticle(w, h);</b>
|
||
<b class="nc"> int advance = rnd.nextInt(800) + 100;</b>
|
||
<b class="nc"> for (int f = 0; f < advance; f++) p.update();</b>
|
||
<b class="nc"> if (!p.isDead(w, h)) {</b>
|
||
<b class="nc"> p.addTo(pane);</b>
|
||
<b class="nc"> p.updateVisual(w, h);</b>
|
||
<b class="nc"> particles.add(p);</b>
|
||
}
|
||
}
|
||
}
|
||
|
||
<b class="nc"> if (now - lastSpawn > SPAWN_INTERVAL_NS && particles.size() < MAX_PARTICLES) {</b>
|
||
<b class="nc"> lastSpawn = now;</b>
|
||
<b class="nc"> int count = rnd.nextInt(2) + 1;</b>
|
||
<b class="nc"> for (int i = 0; i < count && particles.size() < MAX_PARTICLES; i++) {</b>
|
||
<b class="nc"> Particle p = spawnParticle(w, h);</b>
|
||
<b class="nc"> p.addTo(pane);</b>
|
||
<b class="nc"> particles.add(p);</b>
|
||
}
|
||
}
|
||
|
||
<b class="nc"> Iterator<Particle> it = particles.iterator();</b>
|
||
<b class="nc"> while (it.hasNext()) {</b>
|
||
<b class="nc"> Particle p = it.next();</b>
|
||
<b class="nc"> for (int s = 0; s < STEPS_PER_FRAME; s++) p.update();</b>
|
||
<b class="nc"> if (p.isDead(w, h)) {</b>
|
||
<b class="nc"> p.removeFrom(pane);</b>
|
||
<b class="nc"> it.remove();</b>
|
||
} else {
|
||
<b class="nc"> p.updateVisual(w, h);</b>
|
||
}
|
||
}
|
||
}
|
||
|
||
private Particle spawnParticle(double w, double h) {
|
||
<b class="nc"> int corner = rnd.nextInt(4);</b>
|
||
<b class="nc"> double margin = 0.12;</b>
|
||
double x, y;
|
||
<b class="nc"> switch (corner) {</b>
|
||
<b class="nc"> case 0 -> { x = rnd.nextDouble() * w * margin; y = h - rnd.nextDouble() * h * margin; }</b>
|
||
<b class="nc"> case 1 -> { x = w - rnd.nextDouble() * w * margin; y = h - rnd.nextDouble() * h * margin; }</b>
|
||
<b class="nc"> case 2 -> { x = rnd.nextDouble() * w * margin; y = rnd.nextDouble() * h * margin; }</b>
|
||
<b class="nc"> default -> { x = w - rnd.nextDouble() * w * margin; y = rnd.nextDouble() * h * margin; }</b>
|
||
}
|
||
<b class="nc"> return new Particle(x, y, w, h, corner, rnd);</b>
|
||
}
|
||
|
||
// ── Particle ──────────────────────────────────────────────────────────────
|
||
|
||
private static class Particle {
|
||
|
||
double x, y, vx, vy;
|
||
double life;
|
||
double size;
|
||
double wobblePhase, wobbleSpeed, wobbleAmp;
|
||
final int type;
|
||
final Random rnd;
|
||
|
||
final Circle core;
|
||
final Circle glow; // non-null only for embers
|
||
|
||
<b class="nc"> Particle(double x, double y, double w, double h, int corner, Random rnd) {</b>
|
||
<b class="nc"> this.x = x;</b>
|
||
<b class="nc"> this.y = y;</b>
|
||
<b class="nc"> this.life = 1.0;</b>
|
||
<b class="nc"> this.rnd = rnd;</b>
|
||
<b class="nc"> this.type = weightedType(rnd);</b>
|
||
|
||
<b class="nc"> double targetX = (corner == 0 || corner == 2) ? w * 0.75 : w * 0.25;</b>
|
||
<b class="nc"> double targetY = (corner == 0 || corner == 1) ? h * 0.25 : h * 0.75;</b>
|
||
<b class="nc"> double baseAngle = Math.atan2(targetY - y, targetX - x);</b>
|
||
<b class="nc"> double angle = baseAngle + (rnd.nextDouble() - 0.5) * (Math.PI / 3.5);</b>
|
||
|
||
double speed;
|
||
<b class="nc"> if (type == 0) { // ember</b>
|
||
<b class="nc"> speed = 0.5 + rnd.nextDouble() * 0.7;</b>
|
||
<b class="nc"> size = rnd.nextDouble() * 3 + 2;</b>
|
||
<b class="nc"> glow = new Circle(size * 2.2);</b>
|
||
<b class="nc"> core = new Circle(size / 2);</b>
|
||
<b class="nc"> } else if (type == 1) { // spark</b>
|
||
<b class="nc"> speed = 1.5 + rnd.nextDouble() * 2.0;</b>
|
||
<b class="nc"> size = rnd.nextDouble() * 1.5 + 0.5;</b>
|
||
<b class="nc"> glow = null;</b>
|
||
<b class="nc"> core = new Circle(size / 2);</b>
|
||
} else { // dust
|
||
<b class="nc"> speed = 0.2 + rnd.nextDouble() * 0.35;</b>
|
||
<b class="nc"> size = rnd.nextDouble() * 8 + 5;</b>
|
||
<b class="nc"> glow = null;</b>
|
||
<b class="nc"> core = new Circle(size);</b>
|
||
<b class="nc"> core.setFill(Color.color(0.55, 0.38, 0.22));</b>
|
||
}
|
||
|
||
<b class="nc"> vx = Math.cos(angle) * speed;</b>
|
||
<b class="nc"> vy = Math.sin(angle) * speed;</b>
|
||
<b class="nc"> wobblePhase = rnd.nextDouble() * Math.PI * 2;</b>
|
||
<b class="nc"> wobbleSpeed = 0.025 + rnd.nextDouble() * 0.04;</b>
|
||
<b class="nc"> wobbleAmp = 0.1 + rnd.nextDouble() * 0.4;</b>
|
||
}
|
||
|
||
private static int weightedType(Random rnd) {
|
||
<b class="nc"> double r = rnd.nextDouble();</b>
|
||
<b class="nc"> if (r < 0.55) return 0;</b>
|
||
<b class="nc"> if (r < 0.78) return 1;</b>
|
||
<b class="nc"> return 2;</b>
|
||
}
|
||
|
||
void addTo(Pane pane) {
|
||
<b class="nc"> if (glow != null) pane.getChildren().add(glow);</b>
|
||
<b class="nc"> pane.getChildren().add(core);</b>
|
||
}
|
||
|
||
void removeFrom(Pane pane) {
|
||
<b class="nc"> pane.getChildren().remove(core);</b>
|
||
<b class="nc"> if (glow != null) pane.getChildren().remove(glow);</b>
|
||
}
|
||
|
||
void update() {
|
||
<b class="nc"> wobblePhase += wobbleSpeed;</b>
|
||
<b class="nc"> vx += Math.sin(wobblePhase) * wobbleAmp * 0.05;</b>
|
||
<b class="nc"> vy += Math.cos(wobblePhase) * wobbleAmp * 0.02;</b>
|
||
<b class="nc"> x += vx;</b>
|
||
<b class="nc"> y += vy;</b>
|
||
<b class="nc"> if (type == 1) life -= 0.008 + rnd.nextDouble() * 0.006;</b>
|
||
}
|
||
|
||
boolean isDead(double w, double h) {
|
||
<b class="nc"> double pad = size * 4;</b>
|
||
<b class="nc"> return x < -pad || x > w + pad || y < -pad || y > h + pad</b>
|
||
|| (type == 1 && life <= 0);
|
||
}
|
||
|
||
void updateVisual(double w, double h) {
|
||
<b class="nc"> double edge = Math.min(w, h) * 0.05;</b>
|
||
<b class="nc"> double fadeX = Math.min(x / edge, Math.min((w - x) / edge, 1.0));</b>
|
||
<b class="nc"> double fadeY = Math.min(y / edge, Math.min((h - y) / edge, 1.0));</b>
|
||
<b class="nc"> double posAlpha = Math.max(0, Math.min(fadeX, fadeY));</b>
|
||
<b class="nc"> double lifeAlpha = (type == 1) ? Math.min(life * 2.0, 1.0) : 1.0;</b>
|
||
<b class="nc"> double alpha = posAlpha * lifeAlpha;</b>
|
||
|
||
<b class="nc"> core.setTranslateX(x);</b>
|
||
<b class="nc"> core.setTranslateY(y);</b>
|
||
|
||
<b class="nc"> if (type == 0) {</b>
|
||
<b class="nc"> double dist = Math.sqrt((x - w/2) * (x - w/2) + (y - h/2) * (y - h/2));</b>
|
||
<b class="nc"> double hotness = Math.max(0, 1.0 - dist / (Math.sqrt(w * w + h * h) * 0.4));</b>
|
||
<b class="nc"> double g = 0.3 + hotness * 0.5;</b>
|
||
<b class="nc"> core.setFill(Color.color(1.0, g, 0.0));</b>
|
||
<b class="nc"> core.setOpacity(alpha * 0.88);</b>
|
||
<b class="nc"> glow.setTranslateX(x);</b>
|
||
<b class="nc"> glow.setTranslateY(y);</b>
|
||
<b class="nc"> glow.setFill(Color.color(1.0, g * 0.35, 0.0));</b>
|
||
<b class="nc"> glow.setOpacity(alpha * 0.10);</b>
|
||
<b class="nc"> } else if (type == 1) {</b>
|
||
<b class="nc"> double brightness = Math.min(life * 2.5, 1.0);</b>
|
||
<b class="nc"> core.setFill(Color.color(1.0, brightness * 0.85 + 0.15, brightness * 0.15));</b>
|
||
<b class="nc"> core.setOpacity(alpha);</b>
|
||
} else {
|
||
<b class="nc"> core.setOpacity(alpha * 0.20);</b>
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</code>
|
||
</pre>
|
||
</div>
|
||
|
||
<script type="text/javascript">
|
||
(function() {
|
||
var msie = false, msie9 = false;
|
||
/*@cc_on
|
||
msie = true;
|
||
@if (@_jscript_version >= 9)
|
||
msie9 = true;
|
||
@end
|
||
@*/
|
||
|
||
if (!msie || msie && msie9) {
|
||
hljs.highlightAll()
|
||
hljs.initLineNumbersOnLoad();
|
||
}
|
||
})();
|
||
</script>
|
||
|
||
<div class="footer">
|
||
|
||
<div style="float:right;">generated on 2026-06-14 21:53</div>
|
||
</div>
|
||
</body>
|
||
</html>
|