2D-Spiel Fragen und Hilfe bei Programmierung

So ein Mist, die Zählvariable in der for Schleife hatte sich nicht vertragen, ist jetzt auch ein float.

Warum wird aber immer noch ein weisser Bildschirm angezeigt?
Habe ich nen schweren Fehler oder fehlt mir einfach nur der oben genannte Timer?
 
denk an die clipping planes!

Und halt an das push, oder wie das grad nochmals hies.

Auch musst du darauf achten, dass du überhaupt im Fenster zeichnest. Die Werte beziehen sich nicht! Auf die Anzahl Pixel.
 
Machs halt einfach so:
Code:
       x = ball1.radius*cosf((float)z*(Pi/180.0f));
       y = ball1.radius*sinf((float)z*(Pi/180.0f));
Bzw.
Code:
       x = ball2.radius*cosf((float)c*(Pi/180.0f));
       y = ball2.radius*sinf((float)c*(Pi/180.0f));
Ansonsten solltest du trotzdem mal aufpassen, mit was für Datentypen du arbeitest. Der Compiler hat ja noch paar Meldungen mehr, wo OpenGL gerne float hätte, du aber int übergibst oder eben genau andersrum.
 
Ich finde das mit dem float zu int find ich gar nicht so schlecht, da rechne ich halt mit hoher Genauigkeit die Vektoren aus und gebe sie halt weniger genau aus, ein halber Pixel stört ja keinen.

Mein anderes Problem ist, dass ich jetzt noch glFlush() und danach glutSwapBuffers (is des wegen dem doppelten Buffer, dass der mit einem Rechnet und den anderen in der Weile ausgibt und die immer tauscht?) hnzugegügt hab.
Es kommt aber nur ein blauer Strich von lings unten bis ca. Mitte des Bildschirms, sonst passiert nichts.

Edit: Liegt es daran, dass, wie Skysnake sagte, die "Werte sich nicht auf die Pixel beziehen"?
OpenGL fängt doch links unten bei 0,0 an und hört (in meinem Fall) rechts oben bei 1280,720 auf, oder?
 
- das mit float -> int ist auch noch okay, aber später kann sich eine so kleine ungenauigkeit extrem fortpflanzen! Ich hatte das z.B. letzte Woche mit Zeitrechnungen. Da habe ich float statt double (welche ich eign vom System erhalten würde) genutzt und ging auch alles gut, aber so nach einiger Zeit wurden viele Bewegungen ruckelig, da sie eben nur die float-Werte zur Grundlage hatten und das linear erhöht verringert die Genauigkeit auch linear^^
- Üblicherweise kannst du die Bufferanzahl auch bei OpenGL einstellen. 2 ist typisch und eigentlich auch das beste: Ein Bild wird gerade berechnet und das andere wird angezeigt, dann wird getauscht usw. wie du schon sagtest. Und das tauschen muss bei vielen APIs explizit gemacht werden
- Wie die Bildschirmkoordinaten bei OpenGL gehandhabt werden weiß ich nicht, aber ich vermute mal (0,0) in einer Ecke und (1,1) in der gegenüberliegenden Ecke. (Intern ist dann ein Punkt eben eine Pixelkoordinate (x*Width,y*Height) wobei (0,0) <= (x,y) <= (1,1) was eben den Grenzen (0*1280, 0*720) und (1*1280, 1*720) entspricht. So isses jedenfalls bei D3D
 
Zuletzt bearbeitet:
Ich habe immer mal wieder von einer Projektionsmatrix und der Funktion glViewPort gelesen, liegt es daran, dass ich damit den gezeichneten Breich begrenzen muss?
 
es gibt den viewport, modellview, matrixview usw.

Daher kannste nicht davon ausgehen, wo wa ist. Du kannst ja auch noch die Kamera drehen usw usw.

Bei mir ist es z.b. So, da alles >2 außerhalb des Bildschirms ist, und genau das passiert bei dir auch. Du zeichnest von der Mitte nach außen, und mehr siehst du halt nicht weil außerhalb des displays.

Wie man genau eine "pixelgenaue" darstellung macht weiß ich auch nicht, geht aber wahrscheinlich auch gar nicht. Mit float/double bei der initialisierung wird wahrscheinlich auf den Bereich 0-1 abgebildet. Ähnlich wie das bei glColor auch der Fall ist.
 
So, ich hab jetzt den Code der Funktion änderung hinzugefügt, hat aber das Problem nicht behoben, im Gegensatz: Der blaue Strich ist jetzt volkommen weg.
Hier der Code:
Code:
// Ball Simulation.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
//
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <Windows.h>
#include <GL/glew.h>
#include <gl/freeglut.h>
#define Pi 3,14159265358979323846
using namespace std;
//Bildschirmauflösung ermitteln
unsigned int blänge = GetSystemMetrics(SM_CXSCREEN), bbreite = GetSystemMetrics(SM_CYSCREEN); 
struct kugel
{
float position[2];
float geschwindigkeit[2]; 
unsigned int radius;
}ball1, ball2;
void ballinit()
{ //Klasse initialisieren Ball1 
ball1.position[0]=110;
ball1.position[1]=110;
ball1.geschwindigkeit[0]=0;
ball1.geschwindigkeit[1]=5;
ball1.radius=50;
//Ball2
ball2.position[0]=500;
ball2.position[1]=500;
ball2.geschwindigkeit[0]=10;
ball2.geschwindigkeit[1]=0;
ball2.radius=100;
};
void ballupdate()
{ 
for(int stelle = 0; stelle<=1; stelle++)
{
ball1.position[stelle] = ball1.position[stelle] + ball1.geschwindigkeit[stelle];
ball2.position[stelle] = ball2.position[stelle] + ball2.geschwindigkeit[stelle];
} 
}
void kollision()
{ 
//Kollision Bildschirmrand
//Ball1
//rechts /links kollidieren
if( (ball1.position[0] <= (blänge-ball1.radius)) || (ball1.position[0] <= ball1.radius) )
{
ball1.geschwindigkeit[0] = ball1.geschwindigkeit[0] * (-1);
}
//oben /unten
else if( (ball1.position[1] <= (bbreite-ball1.radius)) || (ball1.position[1] <= ball1.radius) )
{
ball1.geschwindigkeit[1] = ball1.geschwindigkeit[1] * (-1);
}
//Ball2
//rechts /links
if( (ball2.position[0] <= (blänge-ball2.radius)) || (ball2.position[0] <= ball2.radius) )
{
ball2.geschwindigkeit[0] = ball2.geschwindigkeit[0] * (-1);
}
//oben /unten
else if( (ball2.position[1] <= (bbreite-ball2.radius)) || (ball2.position[1] <= ball2.radius) )
{
ball2.geschwindigkeit[1] = ball2.geschwindigkeit[1] * (-1);
}
//Kollision untereinander /Abstand ausrechnen

if( sqrt( pow( ball2.position[0]-ball1.position[0], 2) + pow( ball2.position[1]-ball2.position[1], 2) ) <= (ball1.radius+ball2.radius) )
{
//? = atan((x1-x2)/(y2-y1))
//Kollisionsgerade
float gerade=0;
gerade = atan( (ball1.geschwindigkeit[0]-ball2.geschwindigkeit[0])/(ball2.geschwindigkeit[1]-ball1.geschwindigkeit[1]) );
//Spiegelungsmatrix
//vx' = vx cos(2 ?) + vy sin(2 ?)
//vy' = vx sin(2 ?) - vy cos(2 ?) 
//Vektoren spiegeln /x 
ball1.geschwindigkeit[0] = ball1.geschwindigkeit[0]*cos(2*gerade) + ball1.geschwindigkeit[0]*sin(2*gerade);
ball2.geschwindigkeit[0] = ball2.geschwindigkeit[0]*cos(2*gerade) + ball2.geschwindigkeit[0]*sin(2*gerade);
//y
ball1.geschwindigkeit[1] = ball1.geschwindigkeit[1]*sin(2*gerade) - ball1.geschwindigkeit[1]*cos(2*gerade);
ball2.geschwindigkeit[1] = ball2.geschwindigkeit[1]*sin(2*gerade) - ball2.geschwindigkeit[1]*cos(2*gerade);
} 

};
void fenster()
{
//Glut aufrufen und initialisieren 
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(-1, -1);
glutInitWindowSize(blänge, bbreite); 
glutCreateWindow("Ball Simulation"); 
}
void zeichnen()
{
GLfloat x=0, y=0;

//Bildschirm bereinigen
glClearColor(1,1,1,0);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
//Zeichnen
glBegin(GL_LINE_LOOP);
glColor3d(1,0,0);
//Mittelpunkz zeichnen
glVertex2i(ball1.position[0], ball1.position[1]);
for(float z=0;z<=360;z++) 
{ 
//Kreiswerte ausrechnen
x = ball1.radius*cos(z*(Pi/180));
y = ball1.radius*sin(z*(Pi/180));
//Kreisbahn zeichnen
glVertex2i(x,y);
}
//Ball 1 ist fertig
glEnd();
//Ball2
glBegin(GL_LINE_LOOP);
glColor3d(0,0,1);
//Mittelpunkt zeichnen
glVertex2i(ball2.position[0], ball2.position[1]);
for(float c=0;c<=360;c++)
{
//Kreiswerte zeichnen
x = ball2.radius*cos(c*(Pi/180));
y = ball2.radius*sin(c*(Pi/180));
//Kreisbahn zeichnen
glVertex2i(x,y);
}
//Ball2 fertig
glEnd();
//Buffer leeren
glFlush();
//Buffer zur Ausgabe leiten
glutSwapBuffers();

//Position der Bälle aktualisieren
//kollision();
//ballupdate();
}
void änderung(int länge, int breite)
{
double verhältnis;
//Nicht durch 0 teilen
if(breite == 0)
{
breite = 1;
}
verhältnis = 1.0*länge/breite;

//Projektionsmodus
glMatrixMode(GL_PROJECTION);
//Reset
glLoadIdentity();
//Sichtfeld fürs ganze Fenstere
glViewport(0,0,länge,breite);
//Korrekte Perspektive
gluPerspective(45,verhältnis,1,1000);
//Wieder Szene anzeigen
glMatrixMode(GL_MODELVIEW);
}
int _tmain(int argc, char * argv[])
{
//Glut aufrufen
glutInit(&argc, argv);
//Fenster zeichnen
fenster();
//Renderfunktion festlegen
glutDisplayFunc(zeichnen);
//Fenster darf verändert werden
glutReshapeFunc(änderung);
//immer auf neuen Event warten;
glutMainLoop();
return(0);
}
 

Eigentlich dachte ich, dass dies den Sichtbereich an das Fenster anpassen würde, jetzt bin ich komplett ratlos:hail:
 
Habe jetzt nicht wirklich Zeit das alles zu überprüfen aber paar Dinge die mir auffalen:
Das glFlush() kannst du dir sparen, da glutSwapBuffers() intern auch noch einen glFlush aufruft!

Du leerst bei dir nur den Color_Buffer, nicht den Tiefenbuffer! Daher bitte das glClear nehmen:
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

glClearColor rufst du einmal beim Start auf aber nicht jeden Render-Call.

glutInitWindowPosition(-1,-1) ?! Setz es auf 0 und 0.


Ansonsten noch eine Kamera setzen mit gluLookAt() (und geh ruhig ein ganzes stück weg)...
So wie ich das Überblicke, arbeitest du mit ziemlich großen Werten (?!) und da ist die Kamera nötig, da man "standart" zu dicht dran ist.

Soviel erstmal von mir. Und nimm die Dinge bitte ernst (nur das glFlush ist jetzt nicht wirklich schlimm).
 
Ich hab jetzt herausgefunden, dass der Zeichenbereich in der Mitte des Bildschirms (o,o) und an der rechten, oberen Ecke (1,1) hat.
Ist es eigfentlich üblich, damit zu Arbeiten oder sollteman wie oben den Bereich auf die Pixelanzahl des Bildschirms vergrößern?
 
Und woran liegt das? Benutze das gluLookAt() und du hast eine frei definierbare Kamera und eben kein 0-1 mehr.
Natürlich kannst du in diesem Bereich arbeiten aber ich würds lassen. Gerade für andere Dinge machts das nicht gerade einfacher.
 
OK, ich hab das Pixelproblem mit glOrtho gelöst, jetzt ist alles Pixelgenau.
Jatzt hab ich allerdings ein anderes Problem: Wenn ich eine Linie mit absoluten Zahlen zeichne, dann wird sie angezeigt.
Zeichne ich sie aber mit Variablen, so kommt nichts. Woran liegt das?

Code im Anhang.
 
Also Skysnake hat definitiv Recht! Code zeigen der funktioniert und dann den Code zeigen der nicht funktioniert.


Was ich jedoch gerade gesehen habe:
Du nutzt erst glOrtho() und kurz darauf einen gluPerspective() - das ist nicht gerade gewöhnlich. Vorallem, da dein gluPerpective einen FOV von 0 hat - so kann man eig. garnix sehen.
Nimm mal einen üblichen Wert wie 50 oder 60.
 
Code:
[FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000]
//Bildschirm bereinigen [/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000]//zeichnen, swapBuffers benötigt![/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]glBegin(GL_LINES);
glVertex2d(ball1.position[0],ball1.position[1]);
glVertex2d(ball2.position[0],ball2.position[1]);
glEnd();

glBegin(GL_LINES);
glVertex2d(100,100);
glVertex2d(510,510);
glEnd();
glutSwapBuffers();
[/SIZE][/FONT][/SIZE][/FONT]

Das untere wird angezeigt, das obere nicht.

Wenn ich bei dem ersten Wert von gluPerspective 50 oder 60 eingebe, sehe ich nur schwarz.
 
Nagut, vergiss das erstmal mit gluPerspective :S

Da du float nimmst, könntest du Vertex2f nehmen statt d.
Außerdem mach doch mal ein cout und schau, ob die Werte von ball1.position usw. denen von den konstanten Zahlen gleich sind.
 
Ich Idiot!!!!
Hatte die Bälle garnicht initialisiert!

Jetzt werden sie mehr oder weniger wie gewünscht angezeigt und bewegen sich auch. Hab aber noch ein paar Probleme:

1) !! Die Kolission funktioniert überhaupt nicht, hab grad kein Plan, an was das liegen könnte !!:hail:
2) Das Zeichnen wird nur aktualisiert, wenn man das Fenster verschiebt - wie kann ich das ändern?
3) -weniger wichtig- Die Bälle sehen hässlich aus, muss mir da noch was überlegen. Dafür gibts ja ne glu Funktion, nur wie sag ich der die gewünschten Koordinaten??

Den Code poste ich ma hier, häng ihn aber auch noch als .cpp an.

Code:
// Ball Simulation.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
//
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <Windows.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#define Pi 3,14159265358979323846
using namespace std;
//Bildschirmauflösung ermitteln
unsigned int blänge = GetSystemMetrics(SM_CXSCREEN), bbreite = GetSystemMetrics(SM_CYSCREEN); 
struct kugel
{
float position[2];
float geschwindigkeit[2]; 
unsigned int radius;
}ball1, ball2;
void ballinit()
{ //Klasse initialisieren Ball1 
ball1.position[0]=110;
ball1.position[1]=110;
ball1.geschwindigkeit[0]=0;
ball1.geschwindigkeit[1]=5;
ball1.radius=50;
//Ball2
ball2.position[0]=500;
ball2.position[1]=500;
ball2.geschwindigkeit[0]=10;
ball2.geschwindigkeit[1]=0;
ball2.radius=100;
};
void ballupdate()
{ 
for(int stelle = 0; stelle<=1; stelle++)
{
ball1.position[stelle] = ball1.position[stelle] + ball1.geschwindigkeit[stelle];
ball2.position[stelle] = ball2.position[stelle] + ball2.geschwindigkeit[stelle];
} 
}
void kollision()
{ 
//Kollision Bildschirmrand
//Ball1
//rechts /links kollidieren
if( (ball1.position[0] >= (blänge-ball1.radius)) || (ball1.position[0] <= ball1.radius) )
{
ball1.geschwindigkeit[0] = ball1.geschwindigkeit[0] * (-1);
//Debug
cout << "****************************************" << endl << "***" << endl << endl << endl << "***********" << endl;
}
//oben /unten
else if( (ball1.position[1] >= (bbreite-ball1.radius)) || (ball1.position[1] <= ball1.radius) )
{
ball1.geschwindigkeit[1] = ball1.geschwindigkeit[1] * (-1);
}
//Ball2
//rechts /links
if( (ball2.position[0] >= (blänge-ball2.radius)) || (ball2.position[0] <= ball2.radius) )
{
ball2.geschwindigkeit[0] = ball2.geschwindigkeit[0] * (-1);
}
//oben /unten
else if( (ball2.position[1] >= (bbreite-ball2.radius)) || (ball2.position[1] <= ball2.radius) )
{
ball2.geschwindigkeit[1] = ball2.geschwindigkeit[1] * (-1);
}
//Kollision untereinander /Abstand ausrechnen
 
if( sqrt( pow( ball2.position[0]-ball1.position[0], 2) + pow( ball2.position[1]-ball2.position[1], 2) ) <= (ball1.radius+ball2.radius) )
{
//atan((x1-x2)/(y2-y1))
//Kollisionsgerade
float gerade=0;
gerade = atan( (ball1.geschwindigkeit[0]-ball2.geschwindigkeit[0])/(ball2.geschwindigkeit[1]-ball1.geschwindigkeit[1]) );
//Spiegelungsmatrix
//vx' = vx cos(2*gerade) + vy sin(2*gerade)
//vy' = vx sin(2*gerade) - vy cos(2*gerade) 
//Vektoren spiegeln /x 
ball1.geschwindigkeit[0] = ball1.geschwindigkeit[0]*cos(2*gerade) + ball1.geschwindigkeit[0]*sin(2*gerade);
ball2.geschwindigkeit[0] = ball2.geschwindigkeit[0]*cos(2*gerade) + ball2.geschwindigkeit[0]*sin(2*gerade);
//y
ball1.geschwindigkeit[1] = ball1.geschwindigkeit[1]*sin(2*gerade) - ball1.geschwindigkeit[1]*cos(2*gerade);
ball2.geschwindigkeit[1] = ball2.geschwindigkeit[1]*sin(2*gerade) - ball2.geschwindigkeit[1]*cos(2*gerade);
} 
 
};
void ball(float x, float y, int radius, float rot, float grün, float blau)
{
glBegin(GL_LINE_LOOP);
glColor3d(rot,grün,blau);
for(float s=0;s<=360;s++)
{
glVertex2f( (x + (radius*cos(s*(Pi/180)))), (y + (radius*sin(s*(Pi/180)))) );
}
glEnd();
}
void fenster()
{
//Glut aufrufen und initialisieren 
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(0,0);
glutInitWindowSize(blänge, bbreite); 
glutCreateWindow("Ball Simulation"); 
//Farbe fürs löschen festlegen
glClearColor(0,0,0,0);
}
void zeichnen()
{ 
//Bildschirm bereinigen 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); 
//Bälle zeichnen
ball(ball1.position[0],ball1.position[1],ball1.radius,1,1,1);
ball(ball2.position[0],ball2.position[1],ball2.radius,0,0,1);
 
//Alles anzeigen
glutSwapBuffers();
//Position aktualisieren
ballupdate();
//Debug in Konsole
//Bildschirmgröße
cout << blänge << bbreite << endl;
//Position der Bälle
cout << "Ball1: (" << ball1.position[0] << ", " << ball1.position[1] << ")" << endl; 
cout << "Ball2: (" << ball2.position[0] << ", " << ball2.position[1] << ")" << endl;
}
void änderung(int länge, int breite)
{
double verhältnis;
//Nicht durch 0 teilen
if(breite == 0)
{
breite = 1;
}
verhältnis = 1.0*länge/breite; 
//Projektionsmodus
glMatrixMode(GL_PROJECTION);
//Reset
glLoadIdentity(); 
//Sichtfeld fürs ganze Fenstere
glViewport(0,0,länge,breite);
//Korrekte Perspektive
gluPerspective(0,verhältnis,1,100);
//Zeichenbereich an Bildschirm anpassen
glOrtho(0,blänge,0,bbreite,0,1);
//Wieder Szene anzeigen
glMatrixMode(GL_MODELVIEW);
}
int _tmain(int argc, char *argv[])
{ 
//Bälle initialisieren
ballinit();
//Glut aufrufen
glutInit(&argc, argv);
//Fenster zeichnen
fenster();
//Renderfunktion festlegen
glutDisplayFunc(zeichnen);
//Fenster darf verändert werden
glutReshapeFunc(änderung); 
//immer auf neuen Event warten;
glutMainLoop();
 
return(0);
}
 
 
Problem 2:
In deiner zeichnen Funktion gefällt mir ehrlich gesagt nicht so die aktualisierung der Daten.
Führe bitte glutSwapBuffer als vorletztes in der zeichen Funktion aus und unter glutSwapbuffer packst du noch folgendes:
glutPostRedisplay();

Das sollte zumindest das Bild besser machen.

Problem 3: Wie sehen denn deine Bälle aus?
 
Also, jetzt bewegen sich die Bälle zumindest schonmal von alleine (kommt mir n Bisschen langsam vor, aber seis drum).

So ein aktueller Ball ist im Anhang, ist es eigentlich schwer, ihn mit einer Textur zu Füllen?
 

Anhänge

  • Unbenannt.JPG
    Unbenannt.JPG
    19 KB · Aufrufe: 52
Zurück