Backgroundmusik im loop modus


Geepole

Grünschnabel
#1
Hallo,

Ich ( kein Programmierer ) und ein guter freund der Programmierer ist, sind seit geraumer zeit dabei, einen game launcher in WPF bzw C# zu schreiben, ich bin für das Designen der einzelnen elemente verantwortlich, während mein kollege die Funktionen einbaut.
Die application besteht aus mehreren Fenstern, erst öffnet sich ein Introscreen, dann ein Titelmenü / Startmenü, dann gehts zum Loginbereich und anschließend in die Lobby. In jedem dieser fenster wird ein Hintergrundvideo als Background abgespielt. Leider steckt mein Kollege jetzt im hochwassergebiet fest, und da er in unabsehbarer zeit erst wieder erscheinen wird, aber der Launcher ende Juni fertig sein soll, frage ich euch um rat ^.^

Wir hatten ursprünglich vor in jedem fenster außer dem Introscreen ( da dieses video mit ton gerendert wurde ) mit Hintergrundmusik zu versehen. Dh wenn das Introvideo fertig abgespielt ist und dann in den Titelmenü rüber geht, sollte dann automatisch ohne Player musik hörbar sein, dann sollte die musik von screen zu screen wechseln. Ich habe eine menge im internet gelesen und gesucht, aber irgendwie will nichts funktionieren. Vieleicht habt ihr eine idee wie ich es alleine hinbekomme, vielleicht möchte sich auch jemand etwas dazuverdienen und es selbst machen, dann hätte ich auch noch ein paar aufgaben mehr, der Launcher ist zu ca. 90% fertiggestellt, und die Projektdatei habe ich auch. Bei interesse einfach melden.

Vielen dank im vorraus :)
 
#2
Hi.
Ich würde mir ein "MediaElement" (WPF Steuerelement) in das Programm/Fenster einfügen, und diesem dann eine URL zu der Audiodatei übergeben. Im MediaElement kann das Automatische abspielen der Datei deaktiviert werden (ist Standardmäßig auf Autoplay) , und dann kann im CodeBehind das abspielen und abbrechen gesteuert werden.

Code:
<!-- To interactively stop, pause, and play the media, the LoadedBehavior 
           property of the MediaElement must be set to "Manual". -->
    <MediaElement Source="DerOrdner/DieDatei.wav" Name="DerAudioPlayer" 
     Width="450" Height="250" LoadedBehavior="Manual" UnloadedBehavior="Stop" Stretch="None" 
     MediaOpened="Element_MediaOpened" MediaEnded="Element_MediaEnded"/>
Das Autoplay abschalten: LoadedBehavior="Stop"

Dann im Code behind die Datei als URI dem Player Übergeben.

Code:
Me.DerAudioPlayer.Source = New URI(DerOrdner/DieNächsteAudioDatei.wav)
Me.DerAudioPlayer.Play
Im XAML Code ist so etwas wie dieses hier: MediaOpened="Element_MediaOpened" MediaEnded="Element_MediaEnded"
Diese beiden Events können dann benutzt werden, um Looping usw. zu steuern.
MediaOpened is der event wenn das MediaElement eine neue URI (DateiPfad etc.) zugewiesen bekommt.
MediaEnded ist der Event wenn die Datei abgespielt wurde und am Ende angelangt ist.
In diesem Event einfach "Me.MeinAudioPlayer.Play" aufrufen, und die Datei Spielt von Anfang.
Eine Kleinigkeit mit den URI´s wenn eine FileInfo benutzt wird um die Datei zur URI umzuwandfeln, nutze wenn möglich den "FullName" der FileInfo.



Code:
Imports System.IO

Class MainWindow
    Dim AudioDateiListe As New List(Of Uri)

    Private Sub DerAudioPlayer_MediaEnded(sender As Object, e As RoutedEventArgs) Handles DerAudioPlayer.MediaEnded
        Me.DerAudioPlayer.Play()
    End Sub

    Private Sub DerAudioPlayer_MediaOpened(sender As Object, e As RoutedEventArgs) Handles DerAudioPlayer.MediaOpened
        Me.DerAudioPlayer.Play()
    End Sub

    Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        Dim _Ordner As New DirectoryInfo("C:\\DerOrdnerMitDenAudioDateien\")
        For Each File As FileInfo In _Ordner.GetFiles("*.wav")
            AudioDateiListe.Add(New Uri(File.FullName))
        Next
        Me.DerAudioPlayer.Source = AudioDateiListe.First
    End Sub
End Class
Code:
<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
         <MediaElement x:Name="DerAudioPlayer" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100" Visibility="Hidden" LoadedBehavior="Manual"/>

    </Grid>
</Window>

Ich hoffe das ist ein Anhaltspunkt, denn das mit dem "Source" ist eine kleine Hürde, und das mit dem "LoadedBehavior".

In deinem Fall würde ich das LoadedBehavior auf Play lassen, und dann wenn die Fentser wechseln, eine Neue Uri übergeben, er spielt ja von alleine.

Das war jetzt knapp Angerissen, aber so können auch Videos abgespielt werden, also nehme ich an das ihr das MedieElement schon nutzt.

c.u. Joshman
 

Geepole

Grünschnabel
#3
Ich bekomme es einfach nicht hin :/ , Ich hinterlasse mal meinen quellcode, vielleicht möchte jemand diesen erweitern ^^
Muss man eigentlich .wav dateien nehmen oder funktioniert auch .mp3?

Hier mal der Mainwindow.xaml code:

Code:
<Window x:Class="CCWPFLauncher.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="680" Width="1024" WindowStartupLocation="CenterScreen" Icon="/CCWPFLauncher;component/favicon.ico" ResizeMode="CanMinimize" xmlns:my="clr-namespace:CCWPFLauncher">
    <Canvas Name="MyCanvas" Background="Black">
        
    </Canvas>
</Window>
Dann der Mainwindow.xaml.cs code:

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;
using System.Windows.Media.Media3D;
using System.Diagnostics;
using System.Windows.Threading;
using System.Threading;

namespace CCWPFLauncher
{    
  
    public partial class MainWindow : Window
    {
        DispatcherTimer ConnectionCheck = new DispatcherTimer();
        private Boolean IsOffline;

        public MainWindow()
        {
            InitializeComponent();

            this.Title = "FPS: 61 - Crush Card's 2";

            SetScreen(new IntroScreen());
            //SetScreen(new TestScreen());

            App.ServerConnection.ServerMessage += new NetClient.ServerResponse(ServerMessage);

            Helper.LoadBanlist();
        }

        

        private void ServerMessage(string message)
        {
            MessageBox.Show(message, "Server Message", MessageBoxButton.OK);
        }

        public void SetScreen(UserControl newScreen, Boolean offline = false)
        {
            IsOffline = offline;

            MyCanvas.Children.Clear();
            MyCanvas.Children.Add(newScreen);
            Canvas.SetLeft(newScreen, 0);
            Canvas.SetTop(newScreen, 0);
            newScreen.Width = MyCanvas.Width;
            newScreen.Height = MyCanvas.Height;

            if (newScreen is LobbyScreen)
            {
                if (IsOffline)
                {
                    ConnectionCheck.IsEnabled = false;
                }
                else
                {
                    ConnectionCheck.IsEnabled = true;
                    ConnectionCheck.Interval = TimeSpan.FromMilliseconds(8000);
                    ConnectionCheck.Tick += new EventHandler(CheckConnection);
                }
            }
        }

        public void ShowScreen(UserControl newScreen)
        {
            App.lobbyScreen.mediaPause();
            App.lobbyScreen.IsEnabled = false;
            MyCanvas.Children.Add(newScreen);
            Canvas.SetLeft(newScreen, 0);
            Canvas.SetTop(newScreen, 0);
            newScreen.Width = MyCanvas.Width;
            newScreen.Height = MyCanvas.Height;
            Panel.SetZIndex(newScreen, 20);
        }

        public void HideScreen(UserControl Screen)
        {
            MyCanvas.Children.Remove(Screen);
            App.lobbyScreen.IsEnabled = true;
            App.lobbyScreen.mediaPlay();
        }

        private void CheckConnection(object sender, EventArgs e)
        {
            if (!App.ServerConnection.CheckConnection())
            {
                ConnectionCheck.IsEnabled = false;
                if (MessageBox.Show("Verbindung zum Server ging verloren.", "Systemnachricht", MessageBoxButton.OK) == MessageBoxResult.OK)
                {
                    Process process = new Process();
                    ProcessStartInfo startInfos = new ProcessStartInfo(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "-r");
                    process.StartInfo = startInfos;
                    process.Start();
                    Application.Current.Shutdown();
                }
                else
                {
                    Application.Current.Shutdown();
                }
            }
        }
    }
}
Dann noch der Titelbildschirm.xaml code:

Code:
<UserControl x:Class="CCWPFLauncher.TitleScreen"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="650" d:DesignWidth="1014" xmlns:my="clr-namespace:CCWPFLauncher">
    <Canvas Name="TitleCanvas">
        <!-- To interactively stop, pause, and play the media, the LoadedBehavior 
           property of the MediaElement must be set to "Manual". -->
        
        <MediaElement Canvas.Left="0" Canvas.Top="0" Height="650" Name="mediaVideo" Width="1014" />
        <my:TitleButton Canvas.Left="180" Canvas.Top="270" x:Name="online" Height="50" Width="230" />
        <my:TitleButton Canvas.Left="180" Canvas.Top="330" x:Name="option" Height="50" Width="230" />
        <my:TitleButton Canvas.Left="180" Canvas.Top="390" x:Name="website" Height="50" Width="230" />
        <my:TitleButton Canvas.Left="180" Canvas.Top="450" x:Name="offline" Height="50" Width="230" />
        <my:TitleButton Canvas.Left="180" Canvas.Top="510" x:Name="ending" Height="50" Width="230" />
        <my:GameOptions Canvas.Left="454" Canvas.Top="192" x:Name="gameOptions1" />
        
     </Canvas>
   
</UserControl>
und Titelbildschirm.xaml.cs code:

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Media;



namespace CCWPFLauncher
{    

    public partial class TitleScreen : UserControl
    {
        private List<TitleButton> titleButtons = new List<TitleButton>();
        
        public TitleScreen()
        {
            InitializeComponent();

            gameOptions1.Visibility = System.Windows.Visibility.Hidden;
            gameOptions1.IsEnabled = true;


            VideoManager videoManager = new VideoManager("sequenz-start.wmv", mediaVideo);
            mediaVideo.Volume = App.gameConfigs.VideoVolume;
            mediaVideo.Play();
            mediaVideo.MediaEnded += new RoutedEventHandler(mediaElement1_MediaEnded);

            
            titleButtons.Add(online);
            titleButtons.Add(option);
            titleButtons.Add(website);
            titleButtons.Add(offline);
            titleButtons.Add(ending);

            for (int i = 0; i < titleButtons.Count; i++)
            {
                titleButtons[i].Init("tBtnN" + (i + 1).ToString() + ".png", "tBtnH" + (i + 1).ToString() + ".png");

            }

            
            online.MouseUp += new MouseButtonEventHandler(online_MouseUp);
            option.MouseUp += new MouseButtonEventHandler(option_MouseUp);
            website.MouseUp += new MouseButtonEventHandler(website_MouseUp);
            offline.MouseUp += new MouseButtonEventHandler(offline_MouseUp);
            ending.MouseUp += new MouseButtonEventHandler(ending_MouseUp);
            
        }

       
        void online_MouseUp(object sender, MouseButtonEventArgs e)
        {
            App.mainWindow.SetScreen(new LoginScreen(App.pConfig, App.sConfig, App.ServerConnection, App.LoginService));
        }

        void option_MouseUp(object sender, MouseButtonEventArgs e)
        {
            gameOptions1.Visibility = System.Windows.Visibility.Visible;
            gameOptions1.IsEnabled = true;
        }

        void website_MouseUp(object sender, MouseButtonEventArgs e)
        {
            Process.Start("http://www.crushcards.net");
        }

        void offline_MouseUp(object sender, MouseButtonEventArgs e)
        {
            Process.Start("ygopro");
        }

        void ending_MouseUp(object sender, MouseButtonEventArgs e)
        {
            App.Current.Shutdown();
        }
       
        void mediaElement1_MediaEnded(object sender, RoutedEventArgs e)
        {
            mediaVideo.Stop();
            mediaVideo.Play();
        }
         
    }
}
Dann habe ich auch noch einen Video und Musicmanager.cs gefunden

Videomanager.cs:

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows.Controls;
using System.Reflection;
using System.IO;
using System.Windows;
using System.IO.Packaging;

namespace CCWPFLauncher
{
    public class VideoManager
    {
        private string path = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\data\\package\\vid\\";
        private String Filename;
        private MediaElement mediaElement;

        public VideoManager(String _filename, MediaElement _mediaElement)
        {
            this.Filename = _filename;
            this.mediaElement = _mediaElement;

            mediaElement.LoadedBehavior = MediaState.Manual;
            mediaElement.Volume = App.gameConfigs.VideoVolume;
            CopyRessourceFiles(Filename);
            mediaElement.Source = new Uri(path + Filename);
        }

        private void CopyRessourceFiles(String filename)
        {
            if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\data\\package\\vid"))
                System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\data\\package\\vid");

            try
            {
                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}
und der Musikmanager.cs

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Media;
using System.Reflection;
using System.Windows;

namespace CCWPFLauncher
{
    public class MusicManager
    {
        private string path = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\data\\package\\sou\\";
        private String Filename;
        private MediaElement mediaElement;

        public MusicManager(String _filename, MediaElement _mediaElement)
        {
            this.Filename = _filename;
            this.mediaElement = _mediaElement;

            mediaElement.LoadedBehavior = MediaState.Manual;
            mediaElement.Volume = App.gameConfigs.MusicVolume;
            CopyRessourceFiles(Filename);
            mediaElement.Source = new Uri(path + Filename);
        }

        

        private void CopyRessourceFiles(String filename)
        {
            if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\data\\package\\sou"))
                System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\data\\package\\sou");
        
        
        }
    }
}
Ich weiß nicht inwieweit man die gebrauchen kann ^^

Vielen dank im vorraus, aber wie gesagt, ich bin so verzweifelt das ich ich dafür sogar belohnen würde.

Mfg

Martin
 
Zuletzt bearbeitet:
#4
Hi.

Ich mal wieder... tsts wie trantütig von mir in Visual Basic zu denken, und du willst ja C# :)

Nichts desto trotz, habe zwar etwas gebraucht um deinen Code zu lesen, aber geil...

Mir ist C# code zwar geläufig, aber bei Details, da fehlt mir das Knowhow im Syntax Bereich.

Was mir im ersten Moment zu denken gab, war die "CopyRessourceFiles"-Geschichte, die kurz vor der URL-übergabe an das MediaElement stattfindet.
Ich hab nur diese Stelle gelesen, und dachte es könnte ja sein das die Datei noch am Kopieren ist und die URL übergeben wird, aber die Datei noch garnicht da ist.
Also ging ich davon aus das es ein Timingproblem ist.

Und DANN, zisch bumm zack in my face klatsch ;)

Es wird garnichts kopiert in der "CopyRessourceFiles", sondern es wird nur der Ordner erstellt, falls der nicht vorhanden ist.
Mal zur gegenprobe:
Kopiere doch mal eine/alle Audio Datei(n) per hand in den Ordner ("sou"), um zu prüfen ob es das ist was nicht geht...
Wenn er was abspielt, dann musst du nur die "CopyRessourceFiles" fertigstellen, und dort den Datei-Kopierbefehl einpflegen.

Videomanager.cs: Zeile 35 - Die Sub : CopyRessourceFiles
Hier dann die Dateien kopieren...

Code:
  // Use Path class to manipulate file and directory paths.
        string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
        string destFile = System.IO.Path.Combine(targetPath, fileName);

        // To copy a folder's contents to a new location:
        // Create a new target folder, if necessary.
        if (!System.IO.Directory.Exists(targetPath))
        {
            System.IO.Directory.CreateDirectory(targetPath);
        }


// Bis hier ist das in deinem Code fertig, aber der folgende Befehl fehlt

 
        // To copy a file to another location and 
        // overwrite the destination file if it already exists.
        System.IO.File.Copy(sourceFile, destFile, true);


// ALSO DIESER BEFEHL --System.IO.File.Copy(QuellDatei,ZielDatei,True)--
Der Code ist von MSDN: http://msdn.microsoft.com/de-de/library/vstudio/cc148994.aspx


Was ich mich noch stutzig machte war das im "Titelbildschirm.xaml" der LoadedBehavior nicht gleich festgelegt wurde, somit kann dann die CodeBehind geschichte als Fehlerquelle eingegrenzt werden. (Nicht Zwingend, aber zum Testen mal im XAML festlegen)

Dann könnte es zu problemen kommen, wenn die Pfade und das Medialement an eine subroutine bzw. Klasse übergeben werden.
Ich würde einmal ein Versuch wagen, und in der Datei "Videomanager.cs" in Zeile 22 den Code mal zum Testen so ändern:
Code:
   this.Filename = _filename;


// ÄNDERN bitte

   this.Filename = "C:\\Windows\media\Windows Print complete.wav";
Wenn du dann was hörst, dann haben wir das Problem eingegrenzt.
Aber Vorsicht, sind sie Lautsprecher an ist überhaupt was aus dem Rechner zu hören...

Ich glaube hier das Du weist worauf ich hinaus will, bitte teste erstmal ob der WMPlayer was an Lärm/Geräusch wiedergibt...

Die WAV-Datei ist nur eine die auf einem Win7-Rechner mit installiert wird, du kannst jede Datei, die der Windows Media Player abspielt auch im MediaElement abspielen.

Da ich die Pfade nicht getestet habe, kann es sein das du den Pfad mit den Schrägern (/ oder \) ein wenig anpassen musst...

Ich weiss nicht ob und wie in C# die Sonderzeichen Escaped werden. Am besten mal kurz recherche zum Thema "Escapen von Sonderzeichen in Zeichenketten".

Sollte das alles nicht Fruchten. Werde ich Morgen 23.06. zwischen 14:00 und 16:00 mich hier im Forum einloggen. und dann können wir das evtl. per Direkten Kontakt versuchen...


c.u. und TOITOITOI Joshman

An die Morderatorn: Ich werde den Beitrag bei gelegenheit Korrigieren, bitte mich nicht Abmahnen. THX