Skip to content

Commit

Permalink
feat: Implement Fade class and transition effect to level transitions
Browse files Browse the repository at this point in the history
  • Loading branch information
devpedrofurquim committed Oct 29, 2024
1 parent faa0f74 commit fff9933
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 10 deletions.
37 changes: 37 additions & 0 deletions lib/components/fade.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:flame/components.dart';
import 'package:flame/effects.dart';
import 'package:flutter/material.dart';

class FadeEffect extends RectangleComponent {
OpacityEffect? fadeEffect;

FadeEffect(Vector2 screenSize)
: super(
size: screenSize,
anchor: Anchor.topLeft,
paint: Paint()
..color = Colors.black.withOpacity(0), // Start transparent
priority:
100, // High priority to ensure it renders above other components
);

void startFade() {
// If a fade effect is already active, remove it
if (fadeEffect != null) {
fadeEffect?.removeFromParent();
}

// Create a new fade-in effect
fadeEffect = OpacityEffect.to(
1.0, // Target opacity (fully opaque)
EffectController(duration: 1.0), // Duration in seconds
onComplete: () {
// Clear the effect after it completes
fadeEffect = null;
},
);

// Add the new effect to the component
add(fadeEffect!);
}
}
28 changes: 22 additions & 6 deletions lib/components/npc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class NPC extends SpriteAnimationGroupComponent
final List<String> dialogues; // Unique dialogues for each NPC type
double moveSpeed = 50;
Vector2 velocity = Vector2.zero();
Vector2 initialPosition; // Define initialPosition
Vector2 initialPosition;
CustomHitbox hitbox = CustomHitbox(
offsetX: 10,
offsetY: 4,
Expand All @@ -44,7 +44,7 @@ class NPC extends SpriteAnimationGroupComponent
position: Vector2(100, 100),
);

Timer? randomDialogueTimer; // Timer for random dialogues
Timer? randomDialogueTimer;

NPC({
required this.npcCharacter,
Expand Down Expand Up @@ -74,7 +74,7 @@ class NPC extends SpriteAnimationGroupComponent

@override
void onRemove() {
randomDialogueTimer?.stop(); // Stop the timer when NPC is removed
randomDialogueTimer?.stop();
super.onRemove();
}

Expand Down Expand Up @@ -104,7 +104,7 @@ class NPC extends SpriteAnimationGroupComponent
@override
void update(double dt) {
super.update(dt);
randomDialogueTimer?.update(dt); // Update the random dialogue timer
randomDialogueTimer?.update(dt);

final Vector2 currentPlayerPosition = gameRef.player.position;
final double distanceToPlayer = currentPlayerPosition.distanceTo(position);
Expand All @@ -122,16 +122,20 @@ class NPC extends SpriteAnimationGroupComponent
}

void _triggerRandomDialogue() {
if (!playerColliding && !messageDisplayed) {
if (!gameRef.currentlySpeakingNPC &&
!playerColliding &&
!messageDisplayed) {
hudMessage.message = dialogues[Random().nextInt(dialogues.length)];
hudMessage.position = position + Vector2(0, -30);

gameRef.add(hudMessage);
gameRef.currentlySpeakingNPC = true; // Set flag to indicate speaking
messageDisplayed = true;

Future.delayed(Duration(seconds: 3), () {
if (messageDisplayed) {
gameRef.remove(hudMessage);
gameRef.currentlySpeakingNPC = false; // Reset flag after speaking
messageDisplayed = false;
}
});
Expand All @@ -147,7 +151,7 @@ class NPC extends SpriteAnimationGroupComponent
if (other is Player) {
playerColliding = true;

if (other.hasInteracted) {
if (other.hasInteracted && !gameRef.currentlySpeakingNPC) {
playerHasInteracted = true;

hudMessage.message = dialogues[Random().nextInt(dialogues.length)];
Expand All @@ -158,8 +162,17 @@ class NPC extends SpriteAnimationGroupComponent
}

gameRef.add(hudMessage);
gameRef.currentlySpeakingNPC = true; // Set flag to indicate speaking
messageDisplayed = true;

Future.delayed(Duration(seconds: 3), () {
// Check if hudMessage is still a child of the game before removing it
if (gameRef.children.contains(hudMessage)) {
gameRef.remove(hudMessage);
}
gameRef.currentlySpeakingNPC = false; // Reset flag after speaking
messageDisplayed = false;
});
other.hasInteracted = false;
}
}
Expand All @@ -172,6 +185,7 @@ class NPC extends SpriteAnimationGroupComponent
playerColliding = false;
if (messageDisplayed) {
gameRef.remove(hudMessage);
gameRef.currentlySpeakingNPC = false; // Reset flag after player leaves
messageDisplayed = false;
}
current = NPCState.walking;
Expand Down Expand Up @@ -199,6 +213,8 @@ class NPC extends SpriteAnimationGroupComponent
}
}

// Movement methods for NPC types

void _bakerMovement(double dt) {
if (movingLeft) {
velocity.x = -moveSpeed;
Expand Down
38 changes: 34 additions & 4 deletions lib/moonshiner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:flame_audio/flame_audio.dart';
import 'package:flutter/painting.dart';
import 'package:moonshiner_game/components/button.dart';
import 'package:moonshiner_game/components/developer_message.dart';
import 'package:moonshiner_game/components/fade.dart';
import 'package:moonshiner_game/components/level_one.dart';
import 'package:moonshiner_game/components/npc.dart';
import 'package:moonshiner_game/components/player.dart';
Expand All @@ -33,6 +34,8 @@ class Moonshiner extends FlameGame
bool playSounds = true;
double soundVolume = 1.0;

bool currentlySpeakingNPC = false; // Track if an NPC is speaking

String developerMessage =
''; // Shared variable to store the developer message

Expand Down Expand Up @@ -217,14 +220,41 @@ class Moonshiner extends FlameGame

// Loading Next and Previous Levels
Future<void> loadNextLevel() async {
currentLevelIndex = (currentLevelIndex + 1) % levelNames.length;
_loadLevel(currentLevelIndex);
// Add the fade effect component to the game
final fadeEffect = FadeEffect(size);
add(fadeEffect);

// Start the fade-in animation
fadeEffect.startFade();

// Delay loading the next level until the fade-in completes
Future.delayed(Duration(seconds: 1), () {
currentLevelIndex = (currentLevelIndex + 1) % levelNames.length;
_loadLevel(currentLevelIndex);

// Remove the fade effect after the transition
fadeEffect.removeFromParent();
});
}

Future<void> loadPreviousLevel() async {
// Only load the previous level if we aren't at the start
if (currentLevelIndex > 0) {
currentLevelIndex--;
_loadLevel(currentLevelIndex);
// Add the fade effect component to the game
final fadeEffect = FadeEffect(size);
add(fadeEffect);

// Start the fade-in animation
fadeEffect.startFade();

// Delay loading the previous level until the fade-in completes
Future.delayed(Duration(seconds: 1), () {
currentLevelIndex--;
_loadLevel(currentLevelIndex);

// Remove the fade effect after the transition
fadeEffect.removeFromParent();
});
}
}
}

0 comments on commit fff9933

Please sign in to comment.