- PSP Spieleentwicklung - http://psp.anmabagima.de -
Schwarz/Weiß war gestern
Dieser Eintrag stammt von AnMaBaGiMa Am 5.1.2010 @ 19:04 In Einfache 3D Welten | Keine Kommentare
Erstmal die Farbe
Für die Farbe auf der Landschaft brauchen wir eine Textur die die Landschaft farblich darstellt, da die Höhenkarte ja nur Grau-Werte - eben für die Höhe enthält. Ich verwende für die Höhenkarte eine passende Textur die von den Dimensionen die selben Maße hat (512×512) und wie folgt aussieht:

Die Textur müssen wir natürlich auch laden um diese benutzen zu können. Dazu werden wir die Methode, welche uns eine PNG Datei bereits in den Höhenkartenspeicher lädt erweitern und den Speicherplatz dynamisch zuweisen anstelle ein festes array zu definieren.
Die erweiterungen in der Klassendefinition:
class ClPspVoxel : public Cl2dHomebrew {
….
protected:
….
//neuer Parameter zur Aufnahme der gelesenen Daten
bool loadMap(const char* filename, unsigned int* data);
….
//Höhenkarte nun als Zeiger für dynamische Speicher Reservierung
//unsigned int mapData[512][512]; //Höhenwerte der Karte
unsigned int* mapData;
unsigned int* texture;
Die Anpassungen in der Implentierung der Lademethode sehen dann wie folgt aus:
/*
* Laden der Bilddaten aus PNG-File in Datenpuffer
* dazu wird die Vorlage aus der SDK graphics.c genutzt
* der Einfachheit halber gehen wir von Daten 512×512 punkten aus
*/
bool ClPspVoxel::loadMap(const char* filename, unsigned int* data) {
….
//Zeile nun Punkt für Punkt durchgehen und die Farbe in den Puffer übertragen
for (x = 0; x < width; x++) {
u32 color = line[x];
//neuer Zugriff auf den Datenpuffer in linearer Form ->zeile*maxBreite + spalte
//mapData[y][x] = color;
data[y*512 + x] = color;
}
Für die Anpassung der Initialisierungsmethode bei der wir nun den Speicher für die Höhenkarte und die Texture reservieren müssen wir noch das zusätzliche Include malloc.h einbinden.Der Code hierfür sieht dann so aus:
bool ClPspVoxel::init(){
…..
//Speicher für die Höhenkarte
mapData = (unsigned int*)malloc(sizeof(unsigned int)*512*512);
//Höhenkarte laden
loadMap(”altitude.png”, mapData);
//speicher für die Textur
texture = (unsigned int*)malloc(sizeof(unsigned int)*512*512);
loadMap(”landscape.png”, texture);
Um den dynamisch reservierten Speicher wieder freizugeben, wenn er nicht mehr gebraucht wird - das ist ganz wichtig! - platzieren wir folgende zeilen in den Klassendestruktor:
free(mapData); free(texture);
Um die Textur nun bei der Darstellung der Landschaft zu berücksichtigen müssen wir nur geringe Anpassungen in der render Methode vornehmen um auch die neue Art auf die Daten zuzugreifen zu berücksichtigen:
void ClPspVoxel::render() {
….
//Höhe des Voxel
altitude = mapData[voxelY*512 + voxelX]; //mapData[voxelY][voxelX];
//die Farbe dieses Voxel aus der textur lesen
unsigned int color = texture[voxelY*512 + voxelX];
……
// Punkt im Bildschirm
//setPixel(pixelX, pixelY, altitude);
setPixel(pixelX, pixelY, color);
Das Ergebnis sieht schon ganz ordentlich aus:

void ClPspVoxel::render() {
….
//nach dem rendern fragen wir das pad ab.
//wurde der Analog-Stick bewegt ?
SceCtrlData pad;
sceCtrlPeekBufferPositive(&pad, 1);
//die ausrichtung des analog sticks ist
//0 ganz links, 255 ganz rechts
//0 ganz oben und 255 ganz unten.
//für eine Bewegung brauchen wir -x bis +x für links rechts
//und -y bis + y
short moveX, moveY;
moveX = pad.Lx - 127;
moveY = 127 - pad.Ly;
nbsp;
//da wir uns nicht im vollen “Auschlag” des Stix bewegen wollen, sondern
//maximal um 4 Pixel pro durchlauf verringern wir die Werte entsprechend
moveX >>= 5;
moveY >>= 5;
posY+=moveY;
posX+=moveX;
}
Schweben
Nun wollen wir noch über unsere Landschaft “schweben”. Dazu müssen wir die render Methode nur geringfügig anpassen. Bis jetzt ist die Höhe des Betrachters immer fest vorgegeben gewesen. Nun wird diese aber aus der Höhe des Punktes berechnet über dem sich der Betrachter gerade befindet.Zusätzlich bauen wir nach dem zeichnen der Bildpunkte in einer Spalte noch eine Sicherheitsabfrage ein, die verhindert, dass der Strahl weiter verfolgt wird, wenn der Bildschirm schon bis oben hin voll-”gemalt” wurde…
void ClPspVoxel::render() {
…..
rayZ = 81 + (mapData[(posY&511)*512 + (posX&511)] & 255); //384;
….
}while (rayZ < currentAltitude);
}
// wenn der Bildschirm am oberen Rand erreicht ist, brauchen
//wir den strahl nicht weiter verfolgen…
if (pixelY <= 1) break;
Viel Spaß bei den ersten “Flugversuchen”
Dieser Artikel wurde ausgedruckt ab PSP Spieleentwicklung: http://psp.anmabagima.de
URL zum Artikel: http://psp.anmabagima.de/2010/01/05/schwarzweis-war-gestern/
Klicken hier zum Drucken.