import 'package:flame/components.dart'; import 'package:flame/effects.dart'; import 'package:flame/particles.dart'; import 'package:flutter/material.dart'; import 'dart:math'; import 'package:shitman/game/components/base.dart'; enum PoopBagState { placed, lit, burning, extinguished } class PoopBag extends ShitComponent { PoopBagState state = PoopBagState.placed; double burnTimer = 0.0; static const double burnDuration = 3.0; // seconds to burn static const double bagSize = 16.0; double radius = bagSize / 2; late Paint paint; 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), ), ); appLog.finest('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.accelerated( acceleration: Vector2( Random().nextDouble() * 20 - 10, -Random().nextDouble() * 30 - 20, ), position: particle.position, ), ); } void extinguish() { state = PoopBagState.extinguished; removeAll(children.whereType()); // Change to burnt color paint = Paint()..color = const Color(0xFF2F2F2F); appLog.finest('Poop bag has burned out'); } @override void render(Canvas canvas) { super.render(canvas); // Draw the poop bag canvas.drawCircle(Offset(0, 0), radius, paint); // 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; } @override Future reset() async { state = PoopBagState.placed; burnTimer = 0.0; smokeParticles.clear(); paint = Paint()..color = const Color(0xFF8B4513); removeAll(children.whereType()); appLog.finest('Poop bag reset to placed state'); } } class SmokeParticle extends Particle { Vector2 position; SmokeParticle({required this.position}) : super(lifespan: 2.0); @override void render(Canvas canvas) { final paint = Paint() ..color = const Color(0xFF808080).withValues(alpha: 0.5) ..style = PaintingStyle.fill; canvas.drawCircle(Offset(position.x, position.y), 3.0, paint); } }