import 'package:flame/components.dart'; import 'package:flame/effects.dart'; import 'package:flutter/material.dart'; import 'dart:math'; enum PoopBagState { placed, lit, burning, extinguished } class PoopBag extends CircleComponent { PoopBagState state = PoopBagState.placed; double burnTimer = 0.0; static const double burnDuration = 3.0; // seconds to burn static const double bagSize = 16.0; late Vector2 smokeOffset; List smokeParticles = []; @override Future onLoad() async { await super.onLoad(); radius = bagSize / 2; paint = Paint()..color = const Color(0xFF8B4513); // Brown color smokeOffset = Vector2(0, -radius - 5); } void lightOnFire() { if (state == PoopBagState.placed) { state = PoopBagState.lit; burnTimer = 0.0; // Add flame effect add( ScaleEffect.to( Vector2.all(1.2), EffectController(duration: 0.5, infinite: true, reverseDuration: 0.5), ), ); debugPrint('Poop bag is now on fire!'); } } @override void update(double dt) { super.update(dt); if (state == PoopBagState.lit) { burnTimer += dt; // Generate smoke particles if (burnTimer % 0.2 < dt) { // Every 0.2 seconds generateSmokeParticle(); } // Check if fully burned if (burnTimer >= burnDuration) { state = PoopBagState.burning; extinguish(); } } // Update smoke particles smokeParticles.removeWhere((particle) { particle.update(dt); return particle.shouldRemove; }); } void generateSmokeParticle() { final random = Random(); final particle = SmokeParticle( position: position + smokeOffset + Vector2(random.nextDouble() * 10 - 5, random.nextDouble() * 5), ); smokeParticles.add(particle); } void extinguish() { state = PoopBagState.extinguished; removeAll(children.whereType()); // Change to burnt color paint = Paint()..color = const Color(0xFF2F2F2F); debugPrint('Poop bag has burned out'); } @override void render(Canvas canvas) { super.render(canvas); // Draw flame effect when lit if (state == PoopBagState.lit) { final flamePaint = Paint() ..color = Color.lerp( const Color(0xFFFF4500), const Color(0xFFFFD700), sin(burnTimer * 10) * 0.5 + 0.5, )!; // Draw flickering flame canvas.drawCircle( Offset(0, -radius - 5), radius * 0.6 + sin(burnTimer * 15) * 2, flamePaint, ); } // Render smoke particles for (final particle in smokeParticles) { particle.render(canvas); } } bool isNearPosition(Vector2 targetPosition, {double threshold = 30.0}) { return (position - targetPosition).length < threshold; } } class SmokeParticle { Vector2 position; Vector2 velocity; double life; double maxLife; bool shouldRemove = false; SmokeParticle({required this.position}) : velocity = Vector2( Random().nextDouble() * 20 - 10, -Random().nextDouble() * 30 - 20, ), life = 2.0, maxLife = 2.0; void update(double dt) { position += velocity * dt; velocity *= 0.98; // Slight air resistance life -= dt; if (life <= 0) { shouldRemove = true; } } void render(Canvas canvas) { final alpha = (life / maxLife).clamp(0.0, 1.0); final smokePaint = Paint()..color = Color(0xFF666666).withValues(alpha: alpha * 0.3); canvas.drawCircle( Offset(position.x, position.y), 6.0 * (1.0 - life / maxLife), smokePaint, ); } }