Autor Beitrag
lk1990
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Sa 08.03.14 15:34 
Hi

Ich habe letztens angefangen ein rundenbasiertes 2D Seekriegsspiel in C# zu programmieren. Die grafische Ausgabe soll über übereinandergelegte Pictureboxen mit teilweise transparenten Inhalten in Form von -png Bildern erfolgen. Bisher habe ich folgendes unter Benutzung dieses Lösungsansatzes implementiert:

Es gibt einen Hintergrund als PictureBox.

Über diesem Hintergrund liegt eine PictureBox, die die Grafik des Spielerschiffs (semi-transparente .png Grafik) enthält, wobei nach Beendigung eines jeden Spielzuges die Position dieser PictureBox bezogen auf die Position des Schiffs am Ende des vorhergehenden Spielzuges geändert wird:

ausblenden C#-Quelltext
1:
2:
3:
4:
pictureBoxPlayerShip1.BackColor = Color.Transparent;
pictureBoxPlayerShip1.Parent = pictureBoxBackground;

pictureBoxPlayerShip1.Location = new Point(Convert.ToInt32(NewStorage.RestorePlayerPosXNm()), Convert.ToInt32(NewStorage.RestorePlayerPosYNm()));


Zusätzlich zu der Grafik für das Spielerschiff habe ich auch bereits eine Grafik für die Darstellung eines Granateinschlages auf der Wasseroberfläche mit oben beschriebener Methode zu implementieren versucht:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
pictureBoxSplash.BackColor = Color.Transparent;
pictureBoxSplash.Parent = pictureBoxBackground;
pictureBoxSplash.Visible = false//standardmäßig auf false, ausser beim Debuggen.

// wenn eine Granate ins wasser einschlägt (ein paar Konditionen werden auf true überprüft), dann passiert folgendes:

pictureBoxSplash.Visible = true;
pictureBoxSplash.Location = new Point(Convert.ToInt32(NewStorage.RestoreImpactPointXNm()), Convert.ToInt32(NewStorage.RestoreImpactPointYNm()));


Die beiden bisher eingebauten PictureBoxen werden zum Zeitpunkt des 0-ten Spielzuges mit bestimmten Initialwerten dargestellt.
Der 0-te Spielzug wird als vollständiger Spielzug behandelt, nur dass eben statt irgendwelcher Berechnungsverfahren zur Ermittlung der Positionen der Grafiken einfach vordefinierte Initialwerte verwendet werden.

Mein Problem sieht jetzt wie folgt aus:
Bei allen Spiezügen, die auf den 0-ten folgen, wird die pictureBoxSplash Grafik nicht mehr am Bildschirm angezeigt, während des 0-ten Spielzuges jedoch schon (auch an der Position der vordefinierten Initialwerte, vorausgesetzt der Initialwert von PictureBoxSlpash.Visible wurde zwecks Debugging standardmäßig auf true gesetzt). Woran kann das liegen? Die Umpositionierung meiner PictureBoxPlayerShip1 funktioniert einwandfrei. Ich habe bereits folgende Fehlerquellen untersucht und definitiv ausgeschlossen:

Die Werte, die pictureBoxSplash.Location = new Point(); übergeben werden, liegen ausserhalb des darstellenbaren Bereichs.

Die PictureBoxPlayerShip1 sorgt für Probleme der Darstellung der PictureBoxSplash (ausgeschlossen durch vollständiges entfernen der PictureBoxPlayerShip1 aus dem Code - das Problem mit der PictureBoxSplash tritt trotzdem auf).

Die PictureBoxSplash.Location existiert nur lokal zwischen zwei geschwungenen Klammern eines If{} Statements - Der Bug tritt unabhängig von der Position der PictureBoxSplash im Code auf, vorausgesetzt der Code ist so weit korrekt geschrieben, dass er vom Compiler aktzeptiert wird.



Kann mir vielleicht irgendhemand einen Tipp geben?
Vielen Dank im voraus!
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4805
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 08.03.14 17:10 
Hallo,

da sich ja pictureBoxPlayerShip1 und pictureBoxSplash eigentlich gleich verhalten sollen, kann es nur sein, daß du doch irgendwo einen kleinen Fehler in deinem Code hast (in dem hier geposteten sehe ich aber keinen - sofern du sicher bist, daß die Location-Werte richtig sind).

In welcher Ereignismethode führst du denn den Spielzug aus (Button_Click)?

Generell ist es jedoch nicht die beste Möglichkeit, mit PictureBox-Objekten bei einem Spielprojekt zu arbeiten (insbesondere wenn sie überlappen und/oder es viele Objekte sind). Besser wäre es, die gesamten Grafik selber zu zeichnen (im Paint-Ereignis der Form oder eines Panels).
lk1990 Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Sa 08.03.14 19:03 
Danke für deine Antwort.

Die Locationwerte der PictureBoxSplash sind IMO korrekt. Das Spielfeld hat 600x600 Pixel größe und die Locationberechnung d. PictureBoxSplashwerte hat mir bei meinen Tests immer Werte zurückgeben, die innerhalb dieses Bereichs liegen. Aber ich werde noch versuchen anstatt der berechneten Werte für den 0+nten Spielzug einfach mit Sicherheit korrekte vordefinierte Standardwerte für alle Spielzüge zu verwenden. Wenn der Bug dann noch immer auftritt, so kann es nicht an den Locationwerten liegen.

Ich führe den Spielzug in der Button_Click Erignismethode aus. Ursprünglich wollte ich Spielmechanik und GUI zwar strikt voneinander trennen, da ich jedoch noch relativ wenig Erfahrung im Programmieren habe, lässt mein Programmkonzept das nicht ohne signifikante Änderungen zu (ich weiss aber inzwischen, wie ich es richtig machen würde, möchte aber nicht den bereits geschrieben Code zu stark verändern, da dieses Spiel ohnehin nur Lernhilfe für mich selbst dient und nicht veröffentlicht werden soll).

Was genau meinst du mit selbst zeichnen? Zur Laufzeit, mit System.Drawing.Pen zum Beispiel? Ich möchte gerne meine eigenen, mit Photoshop erstellten Grafiken einbinden, da ich mir so die größte Freiheit bei der Darstellung meiner 2D Spielgrafiken erhoffe.

EDIT: Hier noch der Code der Form in der die Darstllung erfolgen soll:
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Battleships.General;
using Battleships.Ships;
using Battleships.PhysicalEnvironment;


namespace Battleships
{
    public partial class MainScreen : Form
    {
        InternalStorage NewStorage = new InternalStorage();
        GlobalEnvironment NewEnvironment = new GlobalEnvironment();
        InOutCheck NewCheck = new InOutCheck();
        InOutConvert NewConvert = new InOutConvert();
        PlayerShip NewPlayerShip = new PlayerShip();
        TurnCountCalculation NewTurnCountCalculation = new TurnCountCalculation();
        PositionCalculation NewPositionCalculation = new PositionCalculation();
        BallisticCalculation NewBallisticCalculation = new BallisticCalculation();
        AmmoCountCalculation NewAmmoCountCalculation = new AmmoCountCalculation();



        public MainScreen()
        {
            InitializeComponent();
        }

        private void MainScreen_Load(object sender, EventArgs e) // dispaly some info, set initial values
        {
            int FirstTurn = 1;
            NewStorage.StoreCurrentNumberOfTurns(FirstTurn);
            this.TurnCounterBox.Text = Convert.ToString(NewStorage.RestoreCurrentNumberOfTurns());

            if (NewStorage.RestoreCurrentNumberOfTurns() == 1)
            {
                NewStorage.StorePlayerPosXM(NewPlayerShip.InitialPositionX);
                NewStorage.StorePlayerPosYM(NewPlayerShip.InitialPositionY);
                double CurrentPlayerPosXNauticalMiles = NewConvert.ConvertMetersToNauticalMiles(NewStorage.RestorePlayerPosXM(), NewEnvironment.ConversionFactorMetersToNauticalMiles);
                double CurrentPlayerPosYNauticalMiles = NewConvert.ConvertMetersToNauticalMiles(NewStorage.RestorePlayerPosYM(), NewEnvironment.ConversionFactorMetersToNauticalMiles);

                int CurrentPlayerAmmoCount = NewAmmoCountCalculation.CalculateCurrentAmmoAmount(NewPlayerShip.InitialAmmo, 0);
                NewStorage.StorePlayerCurrentAmmoCount(CurrentPlayerAmmoCount);
                this.AmmoBox.Text = Convert.ToString(NewStorage.RestorePlayerCurrentAmmoCount());

                // Transparent background...  
                pictureBoxPlayerShip1.BackColor = Color.Transparent;
                pictureBoxSplash.BackColor = Color.Transparent;

                // Change parent for overlay PictureBox...
                pictureBoxPlayerShip1.Parent = pictureBoxBackground;
                pictureBoxSplash.Parent = pictureBoxBackground;

                // Change overlay PictureBox position in new parent...

                pictureBoxPlayerShip1.Location = new Point(Convert.ToInt32(CurrentPlayerPosXNauticalMiles), Convert.ToInt32(CurrentPlayerPosYNauticalMiles));

                pictureBoxSplash.Visible = true;
                pictureBoxSplash.Location = new Point(Convert.ToInt32(0), Convert.ToInt32(0));

            }
        }


        private void ApplySpeed_Click(object sender, EventArgs e) // check input & save speed
        {
            bool IsInt = NewCheck.CheckIfInt(this.SpeedBox.Text);

            if (IsInt == true// check if input has correct format and reset bool
            {
                bool IsInRange = NewCheck.CheckIfIntWithinRange(this.SpeedBox.Text, NewPlayerShip.MaxSpeedKts, NewPlayerShip.MinSpeedKts);

                if (IsInRange == true// check if input is within allowed range, store value and display it in SpeedBox
                {
                    NewStorage.StorePlayerSpeedKts(Convert.ToInt32(this.SpeedBox.Text));
                    this.SpeedBox.Text = Convert.ToString(NewStorage.RestorePlayerSpeedKts());
                }
                else
                {
                    MessageBox.Show("Speed either exceeds maximum speed or is negative. Maximum Speed for this vessel is: " + NewPlayerShip.MaxSpeedKts, "Wrong Speed");
                }

            }
            else
            {
                if (IsInt == false)
                {
                    MessageBox.Show("Input must be Integer.""Wrong Format");
                }
            }
        }

        private void ApplyCourse_Click(object sender, EventArgs e) // check input & save course angle
        {
            bool IsInt = NewCheck.CheckIfInt(this.CourseBox.Text);

            if (IsInt == true// check if input has correct format and reset bool
            {
                bool IsInRange = NewCheck.CheckIfIntWithinRange(this.CourseBox.Text, NewPlayerShip.MaxCourseDegrees, NewPlayerShip.MinCourseDegrees);

                if (IsInRange == true// check if input is within allowed range, store value and display it in CourseBox
                {
                    NewStorage.StorePlayerCourseDegrees(Convert.ToInt32(this.CourseBox.Text));
                    this.CourseBox.Text = Convert.ToString(NewStorage.RestorePlayerCourseDegrees());
                }
                else
                {
                    MessageBox.Show("Course either exceeds maximum angle or is negative. Course must be between 0 and 360 degrees." , "Wrong Course");
                }

            }
            else
            {
                if (IsInt == false)
                {
                    MessageBox.Show("Input must be Integer.""Wrong Format");
                }
            }
        }

        private void ApplyGunAzimuth_Click(object sender, EventArgs e) // check input  & save gun azimuth angle
        {
            bool IsDouble = NewCheck.CheckIfDouble(this.GunHorizontalBox.Text);

            if (IsDouble == true// check if input has correct format and reset bool
            {
                bool IsInRange = NewCheck.CheckIfDoubleWithinRange(this.GunHorizontalBox.Text, NewPlayerShip.MaxGunAzimuthDegrees, NewPlayerShip.MinGunAzimuthDegrees);

                if (IsInRange == true// check if input is within allowed range, store value and display it in GunHorizontalBox
                {
                    NewStorage.StorePlayerGunAzimuthDegrees(Convert.ToInt32(this.GunHorizontalBox.Text));
                    this.GunHorizontalBox.Text = Convert.ToString(NewStorage.RestorePlayerGunAzimuthDegrees());
                }
                else
                {
                    MessageBox.Show("Gun azimuth either exceeds maximum or minimum angle for this vessel. Gun azimuth must be between 0 and " + NewPlayerShip.MaxGunAzimuthDegrees, "Wrong Angle");
                }

            }
            else
            {
                if (IsDouble == false)
                {
                    MessageBox.Show("Input must be Real Number""Wrong Format");
                }
            }
        }

        private void ApplyGunElevation_Click(object sender, EventArgs e) // check input & save gun elevation angle
        {
            bool IsDouble = NewCheck.CheckIfDouble(this.GunVerticalBox.Text);

            if (IsDouble == true// check if input has correct format and reset bool
            {
                bool IsInRange = NewCheck.CheckIfDoubleWithinRange(this.GunVerticalBox.Text, NewPlayerShip.MaxGunElevationDegrees, NewPlayerShip.MinGunElevationDegrees);

                if (IsInRange == true// check if input is within allowed range, store value and display it in GunVerticalBox
                {
                    NewStorage.StorePlayerGunElevationDegrees(Convert.ToInt32(this.GunVerticalBox.Text));
                    this.GunVerticalBox.Text = Convert.ToString(NewStorage.RestorePlayerGunElevationDegrees());
                }
                else
                {
                    string _LocalString1 = Convert.ToString(NewPlayerShip.MaxGunElevationDegrees) + Convert.ToString(NewPlayerShip.MinGunElevationDegrees);
                    MessageBox.Show("Gun elevation either exceeds maximum or minimum angle for this vessel. Gun elevation must be between: " + _LocalString1, "Wrong Angle");
                }

            }
            else
            {
                if (IsDouble == false)
                {
                    MessageBox.Show("Input must be Real Number""Wrong Format");
                }
            }
        }

        private void ApplyGunCharges_Click(object sender, EventArgs e) // check input & save amount of propelling charges to be used
        {
            bool IsInt = NewCheck.CheckIfInt(this.GunPropellingBox.Text);

            if (IsInt == true// check if input has correct format and reset bool
            {
                bool IsInRange = NewCheck.CheckIfIntWithinRange(this.GunPropellingBox.Text, NewPlayerShip.MaxGunPropellingChargesAmount, NewPlayerShip.MinGunPropellingChargesAmount);

                if (IsInRange == true// check if input is within allowed range, store value and display it in GunPropellingBox
                {
                    NewStorage.StorePlayerGunPropellingChargesAmount(Convert.ToInt32(this.GunPropellingBox.Text));
                    this.GunPropellingBox.Text = Convert.ToString(NewStorage.RestorePlayerGunPropellingChargesAmount());
                }
                else
                {
                    MessageBox.Show("Amount of propelling charges either exceeds maximum or minimum for this vessels guns. Number of Propelling Charges mus be between 1 and " + NewPlayerShip.MaxGunPropellingChargesAmount, "Wrong Amount");
                }

            }
            else
            {
                if (IsInt == false)
                {
                    MessageBox.Show("Input must be Integer""Wrong Format");
                }
            }
        }

        private void FireGunSalvo_Click(object sender, EventArgs e) // save if guns are to be fired
        {
            bool _LocalBool = true;
            NewStorage.StorePlayerGunFireThisTurn(_LocalBool);
        }

        private void RadarTurnOn_Click(object sender, EventArgs e) // save if radar is on
        {
            bool _LocalBool = true;
            NewStorage.StorePlayerRadarStatus(_LocalBool);
        }

        private void RadarTurnOff_Click(object sender, EventArgs e) // save if radar is off
        {
            bool _LocalBool = false;
            NewStorage.StorePlayerRadarStatus(_LocalBool);
        }

        private void EndTurn_Click(object sender, EventArgs e) // convert stored input values, calculate turn, store and display results
        {
            //player input conversion
            double _LocalSpeedMs = NewConvert.ConvertKtsToMs(NewStorage.RestorePlayerSpeedKts());
            NewStorage.StorePlayerSpeedMs(_LocalSpeedMs);

            double _LocalSpeedVectorX = NewConvert.ConvertPolarTo2DX(NewStorage.RestorePlayerCourseDegrees(), NewStorage.RestorePlayerSpeedMs());
            NewStorage.StorePlayerSpeedVectorXMs(_LocalSpeedVectorX);

            double _LocalSpeedVectorY = NewConvert.ConvertPolarTo2DY(NewStorage.RestorePlayerCourseDegrees(), NewStorage.RestorePlayerSpeedMs());
            NewStorage.StorePlayerSpeedVectorYMs(_LocalSpeedVectorY);

            double _LocalTotalInitialVelocity = NewConvert.ConvertPropellingChargesToTotalv0(NewStorage.RestorePlayerGunPropellingChargesAmount(), NewPlayerShip.VelocityPerChargeMs);
            NewStorage.StorePlayerGunTotalInitialVelocity(_LocalTotalInitialVelocity);

            double _LocalInitialVelocityVectorXMs = NewConvert.ConvertSphericalTo3DX(NewStorage.RestorePlayerGunTotalInitialVelocity(), NewStorage.RestorePlayerGunElevationDegrees(), NewStorage.RestorePlayerGunAzimuthDegrees());
            NewStorage.StorePlayerInitialVelocityVectorXMs(_LocalInitialVelocityVectorXMs);

            double _LocalInitialVelocityVectorYMs = NewConvert.ConvertSphericalTo3DY(NewStorage.RestorePlayerGunTotalInitialVelocity(), NewStorage.RestorePlayerGunElevationDegrees(), NewStorage.RestorePlayerGunAzimuthDegrees());
            NewStorage.StorePlayerInitialVelocityVectorYMs(_LocalInitialVelocityVectorYMs);

            double _LocalInitialVelocityVectorZMs = NewConvert.ConvertSphericalTo3DZ(NewStorage.RestorePlayerGunTotalInitialVelocity(), NewStorage.RestorePlayerGunElevationDegrees());
            NewStorage.StorePlayerInitialVelocityVectorZMs(_LocalInitialVelocityVectorZMs);

            // player turn number calculation
            int PreviousTurn = NewStorage.RestoreCurrentNumberOfTurns();
            int CurrentTurn = NewTurnCountCalculation.CalculateCurrentTurnNumber(PreviousTurn);
            NewStorage.StoreCurrentNumberOfTurns(CurrentTurn);
            this.TurnCounterBox.Text = Convert.ToString(NewStorage.RestoreCurrentNumberOfTurns());

            // player position calculation
            int CurrentTimeScaleMins = 6;
            double CurrentPlayerPosXMeters = NewPositionCalculation.CalculateNewPosX(NewStorage.RestorePlayerPosXM(), NewStorage.RestorePlayerSpeedVectorXMs(), CurrentTimeScaleMins);
            double CurrentPlayerPosYMeters = NewPositionCalculation.CalculateNewPosY(NewStorage.RestorePlayerPosYM(), NewStorage.RestorePlayerSpeedVectorYMs(), CurrentTimeScaleMins);
            double CurrentPlayerPosXNauticalMiles = NewConvert.ConvertMetersToNauticalMiles(CurrentPlayerPosXMeters, NewEnvironment.ConversionFactorMetersToNauticalMiles);
            double CurrentPlayerPosYNauticalMiles = NewConvert.ConvertMetersToNauticalMiles(CurrentPlayerPosYMeters, NewEnvironment.ConversionFactorMetersToNauticalMiles);
            NewStorage.StorePlayerPosXM(CurrentPlayerPosXMeters);
            NewStorage.StorePlayerPosYM(CurrentPlayerPosYMeters);
            NewStorage.StorePlayerPosXNm(CurrentPlayerPosXNauticalMiles);
            NewStorage.StorePlayerPosYNm(CurrentPlayerPosYNauticalMiles);

            // player ship visual representation
            pictureBoxPlayerShip1.Location = new Point(Convert.ToInt32(NewStorage.RestorePlayerPosXNm()), Convert.ToInt32(NewStorage.RestorePlayerPosYNm()));

            // player ship attack resolution and visual impact representaion
            if (NewStorage.RestorePlayerGunFireThisTurn() == true)
            {
                bool AmmoAvailable;
                if (NewCheck.CheckIntIfAboveZero(NewStorage.RestorePlayerCurrentAmmoCount()))
                {
                    AmmoAvailable = true;
                }
                else
                {
                    AmmoAvailable = false;
                }

                if (AmmoAvailable == true)
                {
                    int CurrentPlayerAmmoCount = NewAmmoCountCalculation.CalculateCurrentAmmoAmount(NewStorage.RestorePlayerCurrentAmmoCount(), NewStorage.RestorePlayerGunPropellingChargesAmount());
                    NewStorage.StorePlayerCurrentAmmoCount(CurrentPlayerAmmoCount);
                    this.AmmoBox.Text = Convert.ToString(NewStorage.RestorePlayerCurrentAmmoCount());
                    double _LocalTimeOfImpactSeconds = NewBallisticCalculation.CalculateImpactTimeZSeconds(NewStorage.RestorePlayerInitialVelocityVectorZMs(), NewEnvironment.ConstantGravitationalAccelerationMs2, NewPlayerShip.DeckHeightMeters, NewPlayerShip.ProjectileMassKg);
                    double _LocalImpactPointYMeters = NewBallisticCalculation.CalculateImpactPointYMeters(NewStorage.RestorePlayerInitialVelocityVectorYMs(), 0, NewStorage.RestorePlayerPosYM(), _LocalTimeOfImpactSeconds, NewPlayerShip.ProjectileMassKg);
                    double _LocalImpactPointXMeters = NewBallisticCalculation.CalculateImpactPointXMeters(NewStorage.RestorePlayerInitialVelocityVectorXMs(), 0, NewStorage.RestorePlayerPosXM(), _LocalTimeOfImpactSeconds, NewPlayerShip.ProjectileMassKg);
                    double _LocalImpactPointXNm = NewConvert.ConvertMetersToNauticalMiles(_LocalImpactPointXMeters, NewEnvironment.ConversionFactorMetersToNauticalMiles);
                    double _LocalImpactPointYNm = NewConvert.ConvertMetersToNauticalMiles(_LocalImpactPointYMeters, NewEnvironment.ConversionFactorMetersToNauticalMiles);
                    NewStorage.StoreImpactPointXNm(_LocalImpactPointXNm);
                    NewStorage.StoreImpactPointYNm(_LocalImpactPointYNm);

                    bool TargetIsHit = false// <- TO DO: method that checks if enemy ships were hit
                    if (TargetIsHit == true)
                    {
                        bool _LocalSplashThisTurn = false;
                        NewStorage.StoreIfPlayerSplash(_LocalSplashThisTurn);
                        //bool _LocalExplodeThisTurn = true
                        //NewStorage.StoreIfPlayerExplode(_LocalExplodeThisTurn)
                        //TO DO: calculate damage done to enemyship
                        //TO DO: check if enemy ship sunk (condition armor value < 0)
                        //TO DO: check if game ends
                    }

                    else
                    {
                        bool _LocalSplashThisTurn = true;
                        NewStorage.StoreIfPlayerSplash(_LocalSplashThisTurn);
                        //bool _LocalExplodeThisTurn = false
                        //NewStorage.StoreIfPlayerExplode(_LocalExplodeThisTurn)

                    }
                }
                else
                {
                    bool _LocalBool = false;
                    NewStorage.StorePlayerGunFireThisTurn(_LocalBool);
                    FireGunSalvo.Enabled = false;
                    this.AmmoBox.Text = Convert.ToString(0);
                }


            }
            else
            {
                bool SplashThisTurn = false;
                NewStorage.StoreIfPlayerSplash(SplashThisTurn);
                //bool _LocalExplodeThisTurn = false
                //NewStorage.StoreIfPlayerExplode(_LocalExplodeThisTurn)
            }
            //pictureBoxExplosion.Visible = NewStorage.RestoreIfPlayerExplode();
            //pictureBoxExplosion.Location = new Point(Convert.ToInt32(NewStorage.RestoreImpactPointXNm()), Convert.ToInt32(NewStorage.RestoreImpactPointYNm()));
            pictureBoxSplash.Visible = NewStorage.RestoreIfPlayerSplash();
            pictureBoxSplash.Location = new Point(Convert.ToInt32(NewStorage.RestoreImpactPointXNm()), Convert.ToInt32(NewStorage.RestoreImpactPointYNm()));
        }
    }
}
lk1990 Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Sa 08.03.14 20:05 
Hi,

ich habe das Problem soeben gelöst. Sollte es jemand anderem mit einem ähnlichen Problem vielleicht weiterhelfen:


Die beiden PictureBoxen (Ship1 & Splash) haben sich bei jedem meiner Testläufe immer überlagert und Ship1 hat dabei Splash verdeckt. Das Spielfeld ist mit 600 x 600 nautischen Meilen (dargestellt auf 600 x 600 Pixeln) so groß, dass bei realistischen Mündingsgeschwindigkeiten (ca 890 m/s, die ballistische Berechnung erfolgt im Gegensatz zur Dartsellung in 3D) das Projektil nie ausserhalb der ca 15x15 Pixel großen Schiffsgrafik laden konnte.

Daraus ergibt sich dann direkt das nächste Problem, das man wohl unter Verwenbdung der PictureBoxen nicht lösen kann.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4805
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: So 09.03.14 10:07 
Hallo,

das ist eben das Problem mit WinForms-Controls und Transparenz (bei sich überlagernden Objekten ist nur das "oberste" zu sehen - Stichworte: Z-Achse sowie BringToFront/SendToBack etc.).

Zum selber Zeichnen meine ich wie z.B. unter myCSharp-Forum: [Tutorial] Zeichnen in Windows-Forms-Programmen (Paint/OnPaint, PictureBox) beschrieben, d.h. alle Objekte werden in einer Paint-Methode gezeichnet (und für Grafiken kannst du dann selber e.Graphics.DrawImage(...) aufrufen).
Ist zwar initial etwas mehr Arbeit, da man nun selber die Datenstrukturen und Logik der Objekte (Grafiken etc.) verwalten muß, man hat dann jedoch komplette Kontrolle über das Zeichnen.

Für dein bisheriges Projekt (wie du selber schreibst: Lernhilfe) würde ich das jedoch ersteinmal nicht mehr machen. Wenn du jedoch neue Projekte dieser Art angehen möchtest, dann solltest du diesen Ansatz wählen (das hat den weiteren Vorteil, daß du so gleich GUI und Logik von vornherein trennen kannst!).

Viel Erfolg noch mit deinem Projekt (bzw. deinen Projekten).
lk1990 Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Di 11.03.14 12:26 
Danke für den Link zu dem Tutorial. Ich habe das Problem mit den sich nicht richtig überlagern wollenden transparenten Bildern zwischenzeitlich so gelöst:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
        private void button1_Click(object sender, EventArgs e)
        {
            var src = new Bitmap("C:/Users/aspire 1/Documents/Visual Studio 2013/Projects/Battleships/Battleships/ship1.png");
            var src1 = new Bitmap("C:/Users/aspire 1/Documents/Visual Studio 2013/Projects/Battleships/Battleships/back2.png");
            var src2 = new Bitmap("C:/Users/aspire 1/Documents/Visual Studio 2013/Projects/Battleships/Battleships/splash1.png");
            var bmp = new Bitmap(250250, PixelFormat.Format32bppPArgb);
            var gr = Graphics.FromImage(bmp);
            
            gr.DrawImage(src1, new Rectangle(00, bmp.Width, bmp.Height));
            gr.DrawImage(src, new Rectangle(001515));
            gr.DrawImage(src2, new Rectangle(20201515));

            this.pictureBox1.Image = bmp;
           
        }


Ist das eine korrekte bzw auch bei größeren 2D Anwendungen sinnvolle vorgehenweise, oder sollte ich doch lieber genau wie in dem Tutorial beschrieben vorgehen, um Probleme bei der Darstellung zu vermeiden (sprich: die PictureBox komplett zu vermeiden versuchen)? Sorry für die vielleicht trivial erscheinende Frage, aber ich meine Programmiererfahrung beträgt insgesamt höchstens 3 Wochen.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4805
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 11.03.14 16:03 
Hallo,

bei größeren Projekten würde ich komplett auf PictureBoxen verzichten, aber solange es jetzt seinen Zweck in deinem Projekt erfüllt, kannst du es so lassen.

Nur einen Tipp noch zu den Bildern:
Statt diese mit absoluten Pfadangaben anzusprechen, kannst du zum einen relative Pfade benutzen:
ausblenden C#-Quelltext
1:
2:
// using System.IO;
Path.Combine(Application.StartupPath, "ship1.png");

Dann solltest du diese Bilder direkt zu deinem VS-Projekt hinzufügen und bei deren Eigenschaft "CopyToOutputDir" auf "Copy if newer" stellen (bei einem deutschen VS entsprechende Bezeichnungen). So werden sie dann automatisch beim Kompilieren in das "bin/Debug" bzw. "bin/Release"-Verzeichnis kopiert). So kannst du dann auch die gesamte Anwendung auf einem anderen Rechner starten, indem du einfach dieses Verzeichnis kopierst.

Und die andere Möglichkeit ist das Hinterlegen der Bilder als Ressourcen (Hinzufügen und Bearbeiten von Ressourcen (Visual C#)).
Du kannst dann die Bilder direkt schon als Bitmap ansprechen, z.B.
ausblenden C#-Quelltext
1:
var src = Properties.Resources.Ship1;					

(und brauchst so die Bilder dann nicht mehr in das Ausgabeverzeichnis kopieren, da sie jetzt direkt in der Anwendung enthalten sind - auch wenn diese dann entsprechend größer wird).