hallöchen zusammen.
ich habe mir mal vorgenommen ein kleines einfaches level für das tolle Spiel, was immer im frühstücksfernsehen kam, "Superball", mit c# zu programmieren.
Falls jemand der name Superball nichts sagt: es ist folgendes spiel:
ein spiel was immer im frühstücksfernsehen kam, wo man mit dem telefon einen ball nach rechts und links bewegen muss um hindernisse zu umgehen.
Nun die Fage. wo fange ich da am besten an...bzw was brauche ich im endefekt alles.
Kann mir einer ein paar tipps geben?
bye bye 😉
Mess with the best die like the rest!
Original von SexyEnemy
Nun die Fage. wo fange ich da am besten an...bzw was brauche ich im endefekt alles.
Auf jedenfall einen Telefonanschluß besorgen. 😁
Und jemanden, der auch mit spielt. 8o
aber im ernst, was kannst du denn so alles?
dass du SDK, Computer, Zeit, etc. hast, versteht sich von alleine
lol...hehe
also für das erste ist schon mal gesorgt...aber ichg laube meine tastatur tut es auch 😉
naja und spielen...man spielt ja eh nur selber und nicht zu zweit 😉
Mess with the best die like the rest!
Hallo,
ich würd das so machen:
Am Anfang schreib ich mir ne einfache Gameloop, die immer wieder dein Spielfeld zeichnet und am Ende einen Pageflip durchführt. (Siehe DX Tutorial hier im Forum)
Mit DirectInput kannst du die Tastatur abfragen. Je nachdem welche Taste du gedrückt hast, würde ich die x-Koordinate deiner Kugel bei jedem Frame inkrementieren bzw. dekremtieren.
Um flüssige Bewegungen zu erzeugen, musst du deine Objekte mit Hilfe der Zeitdifferenz des jeweiligen Frames verschieben.
Die anderen Kugeln, die dir entgegen kommen, würde ich mit einer Zufallszahlen für ihren Startpunkt initialisieren. Und auch hier inkrementierst du die y-Koordinate deiner Objekte bei jedem neuem Frame zeitabhängig.
Ob sich zwei Kugeln treffen, kannst du mit dem Satz des Pythagoras berechen.
Abstand = sqrt( x2 + y2 ). Ist der Abstand kleiner als der Radius beider Kugeln, so liegt eine Kollision vor.
Ich hoffe ich konnte dir ein paar Anreize geben.
I am Jack's smirking revenge.
I am Jack's raging bile duct.
I am Jack's cold sweat.
I am Jack's complete lack of surprise.
I am Jack's broken heart.
I am Jack's wasted life.
Also ich habe jetzt mal einen "ball" und ne grundfläche, die aber noch skaliert und transformiert wird erstellt.
ich wollte nun eine textur auf den ball legen, aber irgendwas habe ich wohl vergessen,
hab eine textur erstellt, doch dann sind meine 3d elemente nur noch schwarz?
ich habe mal den code online gestellt.
vll kann mir einer helfen.
Ach ja, und wie kriege ich die sphäre, welche in Mesh enthalten ist richtig rund machen, da sie so komisch oval ist. habe alle variablen versucht zu ändern, aber es tut sich nix.
Dann hab ich nioch ein problem, und zwar: wenn ich die fenstergröße um 100 kleiner mache, dann sieht man nichts mehr von den figuren...woran liegt es?
ist der view point falsch?
Hier ist mein bisheriger code:
http://www.binchen-online.de/superball.htm
vielen lieben danke
LG: sexyenemy
Mess with the best die like the rest!
Oft gemachter Fehler: Integerdivision. Du berechnest die aspect ratio, indem du Width durch Height teilst. Beides sind int-Werte. Wenn Width < Height ist das Ergebnis gleich 0. Wenn es größer ist, ist es 1 (oder 2, 3, 4 etc.). Daher bekommst du immer Eier-Bälle oder (bei 0) nichts mehr zu sehen. Ändere die Zeile mit der Projection Matrix wie folgt
device.Transform.Projection = Matrix.PerspectiveFovLH( (float)Math.PI / 4, (float)ClientSize.Width / ClientSize.Height, 1.0f, 100.0f );
Wichtig ist der float cast minimal einer der beiden Werte (Width oder Height). Dadurch geschieht die Division so, wie du es erwartest. Übrigens benutze ich hier ClientSize, da das die tatsächliche Anzeigefläche für D3D ist.
MfG VizOne
Cool, dankeschön
jetzt klappt das auch mit der Fenstergröße..super
Aber ich trotzalledem kriege ich immernoch nicht meine Textur auf meine Kugel.
in den Beispielen und Tutorials seh ich das textures immer nur im Zusammenhang mit einem vertex buffer...allerdings muss das doch auch ohne gehen...
bei mir sieht man aber nur noch schwarz...sozusagen...
woran liegt das?
LG: SE
Mess with the best die like the rest!
Das liegt daran, dass die Prefab Methoden von Mesh keine Texturkoordinaten erzeugen.
Du müsstest wie folgt vorgehen:
// format mit position, normale und einem textureset
VertexFormats format = VertexFormats.PositionNormal | VertexFormats.Texture1;
box = Mesh.Box( device, 2.0f, 10.0f, 5.0f );//Höhe | Länge | Breite
Mesh tempBox = box.Clone( box.Options.Value, format, device );
// das alte Mesh wird nicht mehr benötigt
box.Dispose();
// referenz anpassen
box = tempBox;
// locken
Vertex[] verts = (Vertex[])box.VertexBuffer.Lock( 0, typeof( Vertex ), LockFlags.None, box.NumberVertices );
// schreiben
for ( int i = 0; i < verts.Length; ++i ) {
// Koordinaten berechnen
verts[i].Tu = /*...*/;
verts[i].Tv = /*...*/;
}
// lock aufheben
box.VertexBuffer.Unlock();
Fertig!
MfG VizOne
sehe ich das richtig, dass dein vorschlag nur mit einem vertex buffer funzt?
und warum erkennt er Vertex[] nicht?
muss ich da noch ein assembly implementieren?
und wie soll ich denn die vertices berechnen?
man ich bin einfach zu blöd 😦(
Mess with the best die like the rest!
Oh Entschuldigung, Vertex hatte ich per using abgekürzt:
using Vertex = CustomVertex.PositionNormalTextured;
Liest sich einfach besser 😁
Du musst lediglich die Texturkoordinaten einfüllen. Natürlich musst du dir die selbst überlegen, denn die Objekte könnten auf verschiedenste Art und Weise texturiert sein.
(0/0) ist die Ecke links oben, (1/1) ist die Ecke rechts unten.
MfG VizOne
der schluckt das using... nicht
CustonVertex kennt er nicht
Mess with the best die like the rest!
Sorry, wieder mein Fehler 😁
using Vertex = Microsoft.DirectX.Direct3D.CustomVertex.PositionNormalTextured;
MfG VizOne
ui ui ui, das wird wird ja immer bunter hier
also erstmal meckert der compiler nicht mehr rum 😉
ne textur ist immernoch nicht zu sehen, aber als ich die vertex punkte mal auf 0 gesetzt habe bei deinem code passiert a was schreckliches
daraus wird dann das hier:
Hilfe, das wird ja immer schlimmer 😮
Mess with the best die like the rest!
sorry, diesmal war es mein fehler
da ich die textur ja auch meine kugel legen will, hab ich vergessen bei dem zweiten teil des codes die box zu ändern 😉
hab also wieder mein ausgangsbild, aber noch keine Textur 😦(
aktueller code liegt wie immer unter
Mess with the best die like the rest!
Ach ja...
ich habe schon einmal nen KeypressEventhandler eingebaut
wenn ich ihn als eigene klasse mache funktioniert er fantastisch,
nur sobald ich ihn in meinen code einbaue, bricht mein ganzes programm zusammen und setzt auch noch meine cpu auslasten bis zum rand voll auf 100%.
woran das aber schon wieder liegt weiß ich nicht, da der keyhandler an sich ja super funzt.
na guti...werd dann auch mal ins bett
Bis morgen
Nachti
Mess with the best die like the rest!
Du kannst natürlich nicht einfach alle Texturkoordinaten auf (5,3) setzen, sondern musst sie je nach Punkt verschieden berechnen. Zu Testzwecken könntest du das z.B. so machen:
for ( int i = 0; i < verts.Length; ++i ) {
verts[i].Tu = verts[i].X;
verts[i].Tv = verts[i].Y;
}
Übrigens waren einige kleine Fehler im Code. In OnDeviceResizing: Nach dem
texture = TextureLoader.FromFile(device, "D:\\C#\\superball\\superball\\smiley.bmp");
fehlt noch ein
device.SetTexture( 0, texture );
Dafür kann dies weg (in initializeGraphics):
if ( bmp != null ) texture = Texture.FromBitmap( device, bmp, 0, Pool.Managed );
device.SetTexture( 0, texture );
Dass sich der KeyHandler das Programm aufhängt liegt an der MessageBox im Verband mit der Gameloop. Die gameloop sollte entweder aussetzen, wenn die MessageBox angezeigt wird, oder du solltest eine andere Art gameloop benutzen.
Zum Aussetzen ginge so etwas:
bool showMB = false;
public void OnKeyPress(object sender, KeyEventArgs e) {
showMB = true;
MessageBox.Show( this, e.KeyCode.ToString(), "Your input" );
showMB = false;
Invalidate();
}
private void OnPaint(object sender, PaintEventArgs e) {
//...
if ( !showMB ) {
this.Invalidate();
}
}
Auf diese Weise wird nur ein neues Frame gezeichnet, wenn die Messagebox nicht angezeigt wird.
MfG VizOne
da es hier jetzt um Direct3D geht, verschiebe ich das jetz mal ins DirectX Foum...
ich habe mal den teil mit der textur nen bisschen abgewandelt mit materielvon meinem dozenten
die textur ist nun zu sehen aber nun ist meine kugel zu der form geworden die mein dozent in seinem code hat
wie bekomme ich jetzt aus dem ganzen wirrwar der zahlen meine kugel zurück 😮
Vertex[] verts = (Vertex[])sph.VertexBuffer.Lock( 0, typeof( Vertex ), LockFlags.None, sph.NumberVertices );
// schreiben
float arcus_increment = (float)(2.0 * Math.PI / (verts.Length-2)); //cylinder angular increment
float tu_increment = (float)(3.0 / (verts.Length-2)); //1.0 Anzahl der Bilder horizontal
Vector3 v = new Vector3();
for (int i = 0; i < verts.Length; i++) {
float arcus = i * arcus_increment;
v.X = (float)Math.Cos( arcus );
v.Y = (float)Math.Sin( arcus );
if ( i%2 == 0 ) v.Z = 1.0f;
else v.Z = -1.0f; //zigzag between top and bottom
verts_.Position = v; //vertex = (cos,sin,+1) or (cos,sin,-1)
v.Z = 0; //cylinder normals have no Z-component
verts_.Normal = v; //normal = (cos,sin,0)
verts_.Tu = i * tu_increment; //horizontal texture position
if ( i%2 == 0 ) verts_.Tv = 0.0f;
else verts_.Tv = 1.0f; //1.0 vertical zigzag on texture image //anzahl der Reihen der Bilder vertikal
}
Mess with the best die like the rest!
juchu...ich habe es irgendwie mit der textur hinbekommen, aber so richtig die feine art ist das bestimmt nicht
Meine tastaturabfragen funktionieren auch schon mal hervorragend
Was müsste ich nun tun, um verschiedene texturen auf verschieden figuren anzuwenden?
hier mein bisheriges ergebnis
und der aktuelle quellcode
MfG: SE
Mess with the best die like the rest!
Vor dem Rendern eines Meshes die Textur neu setzen (SetTextur).
MfG VizOne
ja das mit setTexture ist klar, nur ich möchte ja verschiedene texturen setzen.
bei den kugeln habe ich es hinbekommen, wie auf dem bild bei der letzten antwort zu sehen ist.
Aber mein Untergund(box) will nicht so richtig eine textur annehmen.
PS: kann man ein Hintergundimage in das fenster legen?
aktueller code wie immer unter: quellcode
mfg: SE
Mess with the best die like the rest!
Einen Hintergrund kann man am besten zeichnen, indem man auf ein Viereck aus zwei Dreiecken eine Textur legt und dieses mit ausgeschaltetem ZBuffer und mit orthogonaler Projektion vor allem anderen rendert.
Da ich gerade Langeweile hatte, habe ich eine Klasse geschrieben, die das übernimmt.
#region Using directives
using System;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
// Ein Vertex des Hintergrundes
using Vertex = Microsoft.DirectX.Direct3D.CustomVertex.PositionTextured;
#endregion
namespace SuperBall {
/// <summary>
/// Rendert eine Textur als Bildhintergrund
/// </summary>
public class BackgroundImage : IDisposable {
private VertexBuffer m_vb;
private Texture m_texture;
private Device m_device;
private StateBlock m_currentStates;
/// <summary>
/// Konstruktor
/// </summary>
/// <param name="device">Das renderdevice. Darf nicht null sein.</param>
/// <param name="imageFile">Name des Hintergrundbildes</param>
public BackgroundImage(Device device, string imageFile) {
// argumente überprüfen
if ( device == null ) {
throw new ArgumentNullException( "device" );
}
if ( imageFile == null ) {
throw new ArgumentNullException( "imageFile" );
}
// vertexbuffer erzeugen...
m_vb = new VertexBuffer( typeof( Vertex ), 4, device, Usage.WriteOnly, VertexFormats.Position | VertexFormats.Texture1, Pool.Managed );
// ... und füllen
Vertex[] verts = (Vertex[])m_vb.Lock( 0, LockFlags.NoSystemLock );
verts[0] = new Vertex( -1, 1, 1, 0, 0 );
verts[1] = new Vertex( 1, 1, 1, 1, 0 );
verts[2] = new Vertex( -1, -1, 1, 0, 1 );
verts[3] = new Vertex( 1, -1, 1, 1, 1 );
m_vb.Unlock();
// textur laden
m_texture = TextureLoader.FromFile( device, imageFile );
m_device = device;
// state-block erstellen
CreateStateBlock();
// auf ein reset reagieren (um den stateblock neu zu erstellen)
m_device.DeviceReset += new EventHandler( HandleDeviceReset );
}
/// <summary>
/// Rendert das Hintergrundbild
/// </summary>
/// <remarks>
/// Nach Ablauf der Methode befindet sich das Device in dem gleichen Zustand
/// wie zuvor.
/// </remarks>
public void Render() {
// aktuelle Einstellungen speichern
m_currentStates.Capture();
try {
// Einstellungen setzen
SetStates();
// Objekt rendern
m_device.DrawPrimitives( PrimitiveType.TriangleStrip, 0, 2 );
} finally {
// alte Einstellungen zurücksetzen
m_currentStates.Apply();
}
}
/// <summary>
/// Befreit nicht mehr benötigte Resourcen
/// </summary>
/// <remarks>
/// Sobald das Objekt nicht mehr benutzt wird, sollte
/// diese Methode aufgerufen werden.
/// </remarks>
public void Dispose() {
// aufräumen...
if ( m_texture != null ) {
m_texture.Dispose();
m_texture = null;
}
if ( m_vb != null ) {
m_vb.Dispose();
m_vb = null;
}
if ( m_currentStates != null ) {
m_currentStates.Dispose();
m_currentStates = null;
}
m_device = null;
}
private void SetStates() {
// alle Einstellungen setzen...
// vertex buffer
m_device.SetStreamSource( 0, m_vb, 0, Vertex.StrideSize );
m_device.SetStreamSource( 1, null, 0 );
m_device.VertexFormat = Vertex.Format;
// textur
m_device.SetTexture( 0, m_texture );
// render states
m_device.RenderState.Lighting = false;
m_device.RenderState.ZBufferEnable = false;
m_device.SamplerState[0].MagFilter = TextureFilter.Linear;
m_device.SamplerState[0].MinFilter = TextureFilter.Linear;
// Transformationsmatrizen setzen
Matrix proj = Matrix.OrthoLH( 2.0f, 2.0f, 0.1f, 2.0f );
Matrix worldView = Matrix.Identity;
m_device.SetTransform( TransformType.World, worldView );
m_device.SetTransform( TransformType.View, worldView );
m_device.SetTransform( TransformType.Projection, proj );
}
private void CreateStateBlock() {
// evtl. erst aufräumen
if ( m_currentStates != null ) {
m_currentStates.Dispose();
m_currentStates = null;
}
// aufzeichnen eines stateblocks einleiten
m_device.BeginStateBlock();
// states für dieses objekt setzen
// hierdurch wird bestimmt, was der stateblock später
// aufzeichnen wird
SetStates();
// fertig :)
m_currentStates = m_device.EndStateBlock();
}
void HandleDeviceReset(object sender, EventArgs e) {
// das device wurde zurückgesetzt - stateblock neu erstellen
CreateStateBlock();
}
}
}
Die Benutzung ist sehr einfach. Einfach eine Membervariable erstellen
using SuperBall;
//...
public class Form1 : Form {
// ...
BackgroundImage background;
//...
}
In InitializeGraphics (nachdem das Device erstellt wurde):
background = new BackgroundImage( device, "hintergrund.bmp" );
Und in OnPaint direkt(!) nach dem BeginScene:
background.Render();
MfG VizOne
der erkennt den namespace nicht 🙁
Mess with the best die like the rest!
habe jetzt das daraus gemacht: SuperBall.SuperBall.BackgroundImage
beim starten kommt jedoch eine SystemArgumentnullException...was heißt das?
Mess with the best die like the rest!
a) Du solltest die Klasse, die ich dir gegeben habe besser in eine eigene Datei kopieren - das ist übersichtlicher und dann klappt's auch mit dem namespace (denke ich)
b) Du darfst BackgroundImage erst erstellen, nachdem du das Device erstellt hast (z.B. ganz am Ende von InitializeGraphics)
MfG VizOne
hab es ja als extra klasse im projekt
aber etzt funzt es...das mit dem device war das problem
Danke die klasse ist supergeil...
habe jetzt einen Timer eingebaut, der die Highscore alle 3 sekunden hochzählen soll.
die score erhöhrt er ohne probleme, aber wie aktualisiere ich jetzt mein Textmesh?
meshScore = Mesh.TextFromFont(device, new System.Drawing.Font("Arial", 8), scoreString, 10f, 0);
private void Timer1_Elapsed(object sender, ElapsedEventArgs e) {
score ++;
scoreString = "Score: " + Convert.ToString(score);
MessageBox.Show("Score: "+scoreString, "Timer Event Raised!");
}
Mess with the best die like the rest!
z.B. so:
private void Timer1_Elapsed(object sender, ElapsedEventArgs e) {
score ++;
scoreString = "Score: " + Convert.ToString(score);
if(meshScore != null) {
meshScore.Dispose();
}
meshScore = Mesh.TextFromFont(device, new System.Drawing.Font("Arial", 8), scoreString, 10f, 0);
//MessageBox.Show("Score: "+scoreString, "Timer Event Raised!");
}
also egal was und wie ich es mache, der wirft immer ne NullReferenceException an der stelle:
object reference not set to ......
meshScore = Mesh.TextFromFont(device, new System.Drawing.Font("Arial", 8), scoreString, 10f, 0);
Mess with the best die like the rest!