Laden...

Forenbeiträge von Mao Ingesamt 14 Beiträge

10.11.2011 - 20:08 Uhr

Hallo stes, hallo Forum,

ich wollte mal wieder was in C# machen und stolperte über diesen Thread (in dem schon echt interessante Aufgaben waren). Im Anhang ist meine Lösung für stes' Aufgabe. Auf das Kopieren des Quellcodes verzichte ich aufgrund der Länge (~180 Zeilen oder so) mal, er findet sich jedoch in der ZIP-Datei.

Sollte stes mit der Lösung einverstanden sein, kann gern jemand anderes die nächste Aufgabe stellen. =)


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.IO;

namespace MouseBall {
    public partial class Form1 : Form {
        public const float BALL_RADIUS = 20;
        public const float KICK_POWER = -15;
        public const float GRAVITY = 0.7f;
        public const float MAX_SPEED = 15;

        // add/change fields as you please!
        private Image _ballImg;
        private PointF _ballPos;
        private PointF _speedVector;
        private int _score;
        private int _highscore;
        private bool _playing;
        private bool _newHighscore;

        public int Score {
            get {
                return _score;
            }
            private set {
                _score = value;
                // ggf. neue Highscore setzen
                if (value > Highscore) {
                    Highscore = value;
                }
         
            }
        }

        public int Highscore {
            get {
                return _highscore;
            }
            private set {
                _highscore = value;
                _newHighscore = true;
            }
        }

        public bool Playing {
            get {
                return _playing;
            }
            private set {
                _playing = value;

                if (value) {
                    _lblStartGame.Hide();
                    _timer.Start();
                }
                else {
                    _timer.Stop();
                    if (_newHighscore) {
                        ShowNewHighscore();
                    }
                    initBall();
                    _lblStartGame.Show();
                    Score = 0;
                    _speedVector = new PointF(0.0f, 0.0f);
                    _newHighscore = false;
                }
            }
        }

        public Form1() {
            InitializeComponent();
            _pnlGame.Paint += new PaintEventHandler(_pnlGame_Paint);
            _pnlGame.MouseClick += new MouseEventHandler(_pnlGame_MouseClick);

            this.initBall();

            // load and resize ball icon
            string s = Path.Combine(
                Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
                "soccer-ball.ico");
            _ballImg = new Bitmap(new Icon(s).ToBitmap());
            _ballImg = new Bitmap(_ballImg, new Size((int)BALL_RADIUS * 2, (int)BALL_RADIUS * 2));
        }

        private void initBall() {
            _ballPos = new PointF(_pnlGame.Width / 2, _pnlGame.Height - BALL_RADIUS);
            _speedVector = new PointF(0.0f, 0.0f);
        }

        private void _pnlGame_Paint(object sender, PaintEventArgs e) {
            Graphics g = e.Graphics;
            // paint middle line
            g.FillRectangle(
                Brushes.White,
                0,
                _pnlGame.Height / 2 - 2,
                _pnlGame.Width,
                4);
            // paint the ball
            g.DrawImage(_ballImg, _ballPos.X - BALL_RADIUS,
                _ballPos.Y - BALL_RADIUS);
        }

        void _pnlGame_MouseClick(object sender, MouseEventArgs e) {
            // Spiel ggf. starten
            if (!Playing) {
                Playing = true;
            }

            // Ball ist nur unterhalb der Mittellinie spielbar
            int centerLine = _pnlGame.Height / 2;
            if (e.Y >= centerLine) {
                float dX = e.X - _ballPos.X;
                float dY = e.Y - _ballPos.Y;
                float distSqr = dX * dX + dY * dY;
                // Ball angeklickt?
                if (distSqr <= BALL_RADIUS * BALL_RADIUS) {
                    _speedVector.Y = KICK_POWER;
                    _speedVector.X = 1.5f * KICK_POWER * dX / BALL_RADIUS;
                }
            }
        }

        private void _timer_Tick(object sender, EventArgs e) {
            _ballPos.Y += _speedVector.Y;
            _ballPos.X += _speedVector.X;
            // Fallgeschwindigkeit begrenzen (lässt sich sonst zu schwer treffen)
            _speedVector.Y = Math.Min(_speedVector.Y + GRAVITY, MAX_SPEED);

            CheckGameOver();
            DoCollisionChecks();
            DoScoring();

            _lblScore.Text = Score.ToString();
            _lblHighscore.Text = Highscore.ToString();
            _pnlGame.Invalidate();
        }

        private void DoScoring() {
            // Hat Ball Mittellinie gerade eben nach oben gekreuzt?
            int centerLine = _pnlGame.Height / 2;
            if ((_ballPos.Y < centerLine) && (_ballPos.Y - _speedVector.Y > centerLine)) {
                Score += 1;
            }
        }

        private void CheckGameOver() {
            // Ball unten? -> Spiel vorbei
            // Ball soll erst ganz verschwunden sein, ist so einfacher spielbar
            if (_ballPos.Y >= _pnlGame.Height + BALL_RADIUS) {
                Playing = false;
            }
        }

        private void DoCollisionChecks() {
            // Kollision mit oberem Spielfeldrand?
            if (_ballPos.Y <= BALL_RADIUS) {
                _ballPos.Y = BALL_RADIUS;
                _speedVector.Y *= -1;
            }

            // Linker Spielfeldrand?
            if (_ballPos.X <= BALL_RADIUS) {
                _ballPos.X = BALL_RADIUS;
                _speedVector.X *= -1;
            }

            // Rechter Spielfeldrand?
            if (_ballPos.X >= _pnlGame.Width - BALL_RADIUS) {
                _ballPos.X = _pnlGame.Width - BALL_RADIUS;
                _speedVector.X *= -1;
            }
        }

        private void ShowNewHighscore() {
            MessageBox.Show("Gratulation, das ist ein neuer Highscore!", "Gratulation",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}


Viele Grüße!

21.02.2009 - 23:02 Uhr

Wenn du später dann mal doch noch eine steile(re) Lernkurve im Bereich Spiele- und Grafikprogrammierung haben willst, würde ich mich mit DirectX oder OpenGL auseinandersetzen, wobei du bei letzterem wahrscheinlich schnellere Erfolge haben wirst - kümmert sich dafür dann aber auch wirklich nur um die Grafik, währenddessen du bei DirectX auch noch Schnittstellen für Sound, Eingabe und anderen "Schnickschnack" hast.

21.02.2009 - 22:57 Uhr

(warum wohl?)

Weil es inkonsequent wäre, fremde Produkte einzusetzen, wenn man selbst eins in der Richtung am Markt positioniert? 😁

09.02.2009 - 11:13 Uhr

Hallo!

Hm, das verändert leider nichts am Problem.
Wie ich jetzt bei weiterem Testen gemerkt hab, gibt's das Problem mit den offenen Ports nur, wenn der Server die Verbindung schließt.
Dieser Code bringts also aufs gleiche:


class Program
{
    static void Main(string[] args)
    {
        TcpListener listener = new TcpListener(IPAddress.Any, 1000)
        listener.Start();

        Socket client = listener.AcceptSocket();
        client.Send(Encoding.UTF8.GetBytes("Hello World!"));
        client.Shutdown(SocketShutdown.Both);
        client.Disconnect(false);
        client.Close();
    }
}

🤔

Viele Grüße!
Mao

08.02.2009 - 21:41 Uhr

Hi!

Ich habe gerade eben mal ein wenig Code verfasst, der das Problem aufzeigt.
Vielleicht fällt jemandem ja etwas auf?


 class Program
    {
        static void Main(string[] args)
        {
            Listener listener = new Listener();
            Thread listenerThread = new Thread(new ThreadStart(listener.Listen));
            listenerThread.Start();

            Console.WriteLine("Zum Beenden Taste drücken...");
            Console.ReadKey(true);
        }

        class Listener
        {
            TcpListener listener;
            
            internal Listener()
            {
                listener=new TcpListener(IPAddress.Any, 1000);
            }

            internal void Listen()
            {
                listener.Start();

                while (true)
                {
                    Socket client=listener.AcceptSocket();
                    Server server= new Server();
                    ThreadPool.QueueUserWorkItem(server.HandleRequest,client);
                }
            }
        }

        class Server
        {
            internal void HandleRequest(Object state)
            {
                Socket client = state as Socket;
                client.Send(Encoding.UTF8.GetBytes("Hello World!"));
                client.Close();
            }
        }

    }

Lass ich den Code laufen und connecte über Telnet auf den Port (1000), dann schickt er mir zwar das "Hello World!" und die Verbindung wird laut Telnet auch geschlossen, ein "netstat -a" zeigt mir aber eine "wartende" Verbindung von Port 1000 zum Port, von dem aus Telnet zum Server verbunden war.
Hat irgendwer eine Idee?

Viele Grüße!
Mao

07.02.2009 - 17:07 Uhr

Hallo zusammen! 😃

Ich schreib gerade an einer kleinen Server-App und beim Testen fiel mir auf, dass Sockets scheinbar - warum auch immer - trotz Close noch eine Weile geöffnet bleiben.
Der Server ist zum einen Teil erstmal der Listener, der auf ankommende Verbindungen wartet, diesen einen neuen Socket verpasst und letztlich die Verarbeitung anstößt. Dazu wird eine neue Server-Instanz erstellt und ihr das Client-Socket übergeben. Den finalen Startschuss gibt dann der Threadpool.
Im Server-Objekt selbst wird abgefragt, was der Client will, entsprechend reagiert, und dann der Socket eigentlich mit einem Shutdown, Disconnect und anschließendem Close geschlossen.
Zum Testen verwende ich den einfachen Telnet-Client, den mir Windows bietet. Der Server-Part funktioniert soweit eigtl, die Verbindung wird auch geschlossen (Telnet schmeißt mich mit dem typischen "Verbindung zu Host verloren." raus) - wie gesagt bloß das Problem, dass der Client-Socket auf Server-Seite scheinbar geöffnet bleibt. Ein "netstat -a" ergibt mir zumindest, dass mein Server noch einen Socket zum Client offen hat (Status: wartend), der Client seinen korrekterweise aber bereits geschlossen hat.

Konkrete Frage: Was könnte daran schuld sein, dass der Socket auf Server-Seite geöffnet bleibt? (Lässt sich da ohne Code evtl. etwas zu sagen?)

Viele Grüße!
Mao

10.01.2009 - 22:35 Uhr

Hallo richtman,

tut mir leid, dass ich dir wahrscheinlich nicht das berichten kann, was du gern hören würdest (ich natürlich auch). Eine Möglichkeit, RAW-Dateien in meinem Programm zu verwenden, hab ich leider nicht.
Eine Lösung ist es leider nicht, bestenfalls eine Umgehung des Problems... Beim ersten Auftreten eines neuen RAWs konvertieren in ein JPEG. Prinzipiell genau das, was ich vermeiden wollte.
Bedauerlicherweise kann ich mir diese Controls auch nicht leisten.

Trotzdem viele Grüße!
Mao

28.12.2008 - 12:39 Uhr

Hallo,

danke erstmal für die Antwort. Nur kenn ich ja bereits die Eigenheiten der Rohdatenformate. 😉
Ich hätte jetzt direkt was gesucht wie dcraw für .Net. Das Problem bin ich jetzt aber erstmal umgangen, ich habe für mein Programm einen anderen Ansatz gewählt.
Wäre allerdings nach wie vor ganz praktisch.

Viele Grüße!
Mao

18.12.2008 - 19:14 Uhr

Hallo C#ler! =)

Für ein neues Projekt bin ich derzeit hinter der Frage her, wie ich denn RAW-Bilder in C# laden könnte. Die ganze Problematik mit den herstellerspezifischen Formaten, manche unter Herstellerverschluss, ist mir bereits bewusst. Gibt ja beispielsweise dcraw für diverse RAW-Ableger. Aber was in Managed Code wäre halt nicht schlecht.
Eine andere Möglichkeit wäre das vorher zwanghafte Umwandeln in DNG, was ich jetzt allerdings nicht ganz so toll fände.

Da armer Schüler wär die beste Möglichkeit natürlich auch noch eine kostenlose Möglichkeit. 😁

PS: Forensuche ergab leider nur ein passendes Thema ohne jegliche Antworten.

Viele Grüße!
Mao

10.09.2008 - 10:44 Uhr

Ah, jetzt hab ich das verstanden. =)

Danke!

09.09.2008 - 18:49 Uhr

Hallo,

find ich ganz nützlich, hatte heute erst vor, mir das mit 'nem Excel-Blatt zu realisieren - aber so ist auch nicht schlecht. 😁

Das mit der Wertigkeit hab ich zur Zeit allerdings noch nicht ganz gerafft - je "unwichtiger" die Note, desto höher die Wertigkeit? Beispielsweise Errechnung der Jahresendnote durch Errechnung des Durchschnitts vom Durchschnitt der Klausuren und dem Durchschnitts der einfachen Leistungskontrollen?

Und ein Bug ist mir bisher auch aufgefallen. Wenn ich ein neues Fach anlege, es anschließend lösche und wieder ein Fach anlege, hab ich wieder beide Fächer.

Viele Grüße! 🙂

08.09.2008 - 18:09 Uhr

AFAIK wurde auch der Code der Betriebssysteme seit NT zunehmend mit C++ geschrieben. (Buch "Showstopper", dort beschrieben hauptsächlich das Grafik-Subsystem)

17.08.2008 - 23:07 Uhr

Die Steuerungssoftware eines realen Kraftwerks, die ich kennen gelernt habe, stellte zwar um die 200 Schaubilder/"Schaltpläne"/Komponentenanordnungen bereit, zur Verfügung standen allerdings "nur" 21 Monitore. Deswegen gab es aber auch so viele Schaltpläne - es konnte beliebig skaliert werden von "ganz grober Aufbau" mit den wichtigsten Gesamtwerten jeweils an den gröbsten Komponenten und Kreisläufen, über den Aufbau einzelner Kreisläufe bis hin zu einzelnen Komponenten. Wäre für die Simulation höchstwahrscheinlich auf Grund der Komplexität nicht zu gebrauchen.
Allerdings könnte man die Elemente alle etwas eindampfen und jeweils nur die aktuellen Werte anzeigen. Einzelne Werte/"Variablen" ändern ließen sich dort über eine extra Pop-Up-Box, die beim Draufklicken auf eine Komponente aufging.
Die Pumpen z.B. verbrauchen in deiner Simulation relativ viel Platz. Verkleiner die Darstellung doch etwas, zeig die aktuelle Leistung daneben/darüber/darunter an. Fehlfunktionen wurden immer blinkend an einer Leiste oben am Bildschirm ausgegeben, außerdem ertönte permanent ein Signalton, solange du die Warnung nicht bestätigt hattest.
Die Analog-Temperatur-Anzeige des Reaktors würde ich auf Grund der Größe auch weglassen.

Viele Grüße! 😉
Mao

16.08.2008 - 15:28 Uhr

Hi!
Tolle Simulation, gefällt mir. 🙂
Was nicht schlecht wäre: Eine redundant ausgelegte Kühlwassernachfüllpumpe.
Zudem würde ich auch befürworten, die Übersicht in das Bedienpanel zu integrieren; kann das aus eigenen Erfahrungen bestätigen.
Weitermachen! 👍