Het maken van een basis 3D-Engine in Java (4 / 5 stap)

Stap 4: Berekening van het scherm

De klasse Screen is waar de meerderheid van de berekeningen zijn gedaan om het programma werkend te krijgen. Als u wilt werken, moet de klasse de volgende invoer:

 import java.util.ArrayList;import java.awt.Color; 

De werkelijke klasse begint als volgt:

 public class Screen { public int[][] map; public int mapWidth, mapHeight, width, height; public ArrayList textures; 

De kaart is het dezelfde kaart gemaakt in de game klasse. Het scherm gebruikt dit om erachter te komen waar de muren zijn en hoe ver weg van de speler hebben. Definieer de grootte van het scherm en altijd moet hetzelfde zijn als de breedte en hoogte van het frame gemaakt in de Game klasse breedte en hoogte. Texturen is een lijst van alle van de texturen, zodat het scherm kan toegang krijgen tot de pixels van de texturen. Nadat de variabelen zijn gedeclareerd hoeven te worden geïnitialiseerd in de constructor als volgt:

 public Screen(int[][] m, ArrayList tex, int w, int h) { map = m; textures = tex; width = w; height = h; } 

Nu zijn tijd om te schrijven van de ene methode de klasse heeft: een update-methode. De methode update worden opnieuw berekend hoe het scherm eruit moet zien voor de gebruiker op basis van hun positie in de kaart. De methode heet voortdurend, en de bijgewerkte array van pixels aan de Game klasse retourneert. De methode begint door het scherm "op te schonen". Het doet dit door alle pixels op de bovenste helft tot één kleur en alle pixels op de bodem naar de andere.

 public int[] update(Camera camera, int[] pixels) { for(int n=0; n<pixels.length/2; n++) { if(pixels[n] != Color.DARK_GRAY.getRGB()) pixels[n] = Color.DARK_GRAY.getRGB(); } for(int i=pixels.length/2; i<pixels.length; i++) { if(pixels[i] != Color.gray.getRGB()) pixels[i] = Color.gray.getRGB(); } 

Na de boven- en onderkant van het scherm worden twee verschillende kleuren ook maakt het lijkt alsof er een vloer en een plafond. Na de pixel is array uitgeschakeld dan is het tijd om te gaan op de belangrijkste berekeningen. Het programma elke verticale balk op het scherm doorlopen en werpt een straal om erachter te komen welke muur op het scherm op die verticale balk worden moet. Het begin van de lus ziet er zo uit:

 for(int x=0; x<width; x=x+1) { double cameraX = 2 * x / (double)(width) -1; double rayDirX = camera.xDir + camera.xPlane * cameraX; double rayDirY = camera.yDir + camera.yPlane * cameraX; //Map position int mapX = (int)camera.xPos; int mapY = (int)camera.yPos; //length of ray from current position to next x or y-side double sideDistX; double sideDistY; //Length of ray from one side to next in map double deltaDistX = Math.sqrt(1 + (rayDirY*rayDirY) / (rayDirX*rayDirX)); double deltaDistY = Math.sqrt(1 + (rayDirX*rayDirX) / (rayDirY*rayDirY)); double perpWallDist; //Direction to go in x and y int stepX, stepY; boolean hit = false;//was a wall hit int side=0;//was the wall vertical or horizontal 

Alles wat er gebeurt hier is sommige variabelen die worden gebruikt door de rest van de lus worden berekend. CameraX is de x-coördinaat van de huidige verticale streep op het vlak van de camera, en de rayDir variabelen maken een vector voor naar de vleug. Alle variabelen die eindigt op DistX of DistY worden berekend zodat het programma controleert alleen voor botsingen op de plaatsen waar de botsingen kunnen eventueel optreden. perpWallDist is dat de afstand tussen de speler de eerste muur de straal botst met. Dit zal later worden berekend. We moeten erachter te komen een paar van de andere variabelen die op basis van de definitie die wij al berekend nadat dat wordt gedaan.

 //Figure out the step direction and initial distance to a sideif (rayDirX < 0) { stepX = -1; sideDistX = (camera.xPos - mapX) * deltaDistX; } else { stepX = 1; sideDistX = (mapX + 1.0 - camera.xPos) * deltaDistX; } if (rayDirY < 0) { stepY = -1; sideDistY = (camera.yPos - mapY) * deltaDistY; } else { stepY = 1; sideDistY = (mapY + 1.0 - camera.yPos) * deltaDistY; } 

Zodra dit is gebeurd het is tijd om erachter te komen waar de straal met een muur botst. Om dit te doen het programma doorloopt een lus waar wordt gecontroleerd als de straal is gekomen in contact met een muur en niet verplaatst naar de volgende mogelijke botsing verwijzen, alvorens opnieuw te controleren.

 //Loop to find where the ray hits a wallwhile(!hit) { //Jump to next square if (sideDistX < sideDistY) { sideDistX += deltaDistX; mapX += stepX; side = 0; } else { sideDistY += deltaDistY; mapY += stepY; side = 1; } //Check if ray has hit a wall if(map[mapX][mapY] > 0) hit = true; } 

Nu we weten waar de straal raakt een muur kunnen we beginnen met het uitzoeken hoe de muur eruit moet zien in de verticale streep wij zijn momenteel op. Om dit te doen we eerst het berekenen van de afstand tot de muur, en gebruik vervolgens die afstand om erachter te komen hoe lang de muur moet worden weergegeven in de verticale strook. Wij vervolgens vertalen die hoogte een start en finish in termen van de pixels op het scherm. De code ziet er zo uit:

 //Calculate distance to the point of impactif(side==0) perpWallDist = Math.abs((mapX - camera.xPos + (1 - stepX) / 2) / rayDirX); else perpWallDist = Math.abs((mapY - camera.yPos + (1 - stepY) / 2) / rayDirY); //Now calculate the height of the wall based on the distance from the camera int lineHeight; if(perpWallDist > 0) lineHeight = Math.abs((int)(height / perpWallDist)); else lineHeight = height; //calculate lowest and highest pixel to fill in current stripe int drawStart = -lineHeight/2+ height/2; if(drawStart < 0) drawStart = 0; int drawEnd = lineHeight/2 + height/2; if(drawEnd >= height) drawEnd = height - 1; 

Nadat dat wordt berekend is het tijd om te beginnen met het uitzoeken wat pixels uit de textuur van de muur daadwerkelijk wordt weergegeven aan de gebruiker. Hiervoor moeten we eerst uitzoeken wat textuur is gekoppeld aan de muur we gewoon hit en dan aan de x-coördinaat op de textuur van de pixels die wordt weergegeven aan de gebruiker achterhalen.

 //add a textureint texNum = map[mapX][mapY] - 1; double wallX;//Exact position of where wall was hit if(side==1) {//If its a y-axis wall wallX = (camera.xPos + ((mapY - camera.yPos + (1 - stepY) / 2) / rayDirY) * rayDirX); } else {//X-axis wall wallX = (camera.yPos + ((mapX - camera.xPos + (1 - stepX) / 2) / rayDirX) * rayDirY); } wallX-=Math.floor(wallX); //x coordinate on the texture int texX = (int)(wallX * (textures.get(texNum).SIZE)); if(side == 0 && rayDirX > 0) texX = textures.get(texNum).SIZE - texX - 1; if(side == 1 && rayDirY < 0) texX = textures.get(texNum).SIZE - texX - 1; 

De x-coördinaat wordt berekend door het nemen van de exacte positie van waar de muur werd geraakt op de 2D kaart en de integerwaarde, waardoor alleen het decimaalteken af te trekken. Dit decimale (wallX) wordt vervolgens vermenigvuldigd met de grootte van de textuur van de muur om de exacte x-coördinaat op de muur van de pixels die we willen vestigen. Zodra we weten dat het enige links te doen berekenen de y-coördinaten van de pixels op de textuur en hen op het scherm tekent. Daartoe we alle pixels op het scherm in de verticale strook we doen berekeningen doorlopen voor en berekenen de de exacte y-coördinaat van de pixel op de textuur. Gebruik dit het programma vervolgens schrijft de gegevens van de pixel op de structuur in de matrix van pixels op het scherm. Het programma maakt ook horizontale muren donkerder dan verticale muren hier om een fundamentele verlichting effect te geven.

 //calculate y coordinate on texturefor(int y=drawStart; y<drawEnd; y++) { int texY = (((y*2 - height + lineHeight) << 6) / lineHeight) / 2; int color; if(side==0) color = textures.get(texNum).pixels[texX + (texY * textures.get(texNum).SIZE)]; else color = (textures.get(texNum).pixels[texX + (texY * textures.get(texNum).SIZE)]>>1) & 8355711;//Make y sides darker pixels[x + y*(width)] = color; } 

Na dat, all that's left in de klasse Screen, klasse is de pixel array terug

 return pixels; 

En de klasse wordt gedaan. Nu alles wat we moeten doen is een paar lijnen van code toevoegen in de Game klasse om het scherm werkend te krijgen. Voeg dit met de variabelen aan de top:

 public Screen screen; 

En in de constructor toevoegen dat dit ergens na texturen is geïnitialiseerd.

 screen = new Screen(map, mapWidth, mapHeight, textures, 640, 480); 

En tot slot in de run methode toevoegen

 screen.update(camera, pixels); 

vlak voor camera.update(map). En het programma is klaar!

Gerelateerde Artikelen

LibreOffice Base Tutorial (het maken van een filter in een formulier)

LibreOffice Base Tutorial (het maken van een filter in een formulier)

In deze Tutorial, ik maak een nieuwe database gemaakt met LibreOffice Base en ik probeer om een filter-formulier met behulp van een externe SQL-Query.Met behulp van tekstvak of keuzelijst met invoervak als parameter voor het zoeken naar items in reco
Het maken van een einde-korrel snijplank - ik maakte het op Techshop

Het maken van een einde-korrel snijplank - ik maakte het op Techshop

hieronder zijn verschillende snijplanken die ik bij Techshop, San Francisco, een lidmaatschap op basis workshop met alle soorten van hulpmiddelen gemaakt heb voor het maken van dingen. Ik heb niet veel ervaring met houtbewerking, dus ik dit project g
Het maken van een drie stenen diamond engagement ring.

Het maken van een drie stenen diamond engagement ring.

Dus, je hebt het meisje van uw dromen ontmoet, en nu wilt u geef haar een mooie ring als een blijvend symbool van uw liefde.Probleem is, kun je niet veroorloven een fancy ontwerper ring, en het je kunt veroorloven zijn massa geproduceerd, bezaaid met
Het maken van een 5 Dollar 5 Minute Birdhouse.

Het maken van een 5 Dollar 5 Minute Birdhouse.

Vorig jaar, verhuisd mijn vriendin en ik naar onze eerste plaats samen, een nucleaire-tijdperk-bungalow met een mooie achtertuin. We wilden zetten sommige vogels huizen, maar we waren allebei erg druk met werk en voorjaar was net om de hoek. Dus, ik
Tutorial over het maken van een zwart Locust boog

Tutorial over het maken van een zwart Locust boog

allereerst ik wil excuses voor eventuele grammaticafouten, en eventuele andere fouten schriftelijk caus ik gebruikte google vertalen voor het vertalen van alle tekst die u hier ziet (Engl is niet mijn eigen languge dus schreef ik allemaal in mijn lan
Het maken van een fossiele duizendpoot.

Het maken van een fossiele duizendpoot.

Na instructable wordt beschreven hoe u een duizendpoot-achtige fossiele.Het grafische deel werd gedaan in 3 NodeBox, een open source applicatie voor generative design (en nog veel meer).De gravure deel werd gedaan op een cnc-Snijder (Trotec - Speedy
Het maken van een Cat(?) Masker met glasvezel

Het maken van een Cat(?) Masker met glasvezel

ik ben niet nieuw voor Instructables, maar ik figuur it's about time ik een account te krijgen en terug te geven aan een website die mij zo veel inspiratie en informatie heeft gegeven. Dit is mijn eerste post, zodat alle opmerkingen en kritiek welkom
Het maken van een DIY borstelloze Gimbal met Arduino

Het maken van een DIY borstelloze Gimbal met Arduino

Dit is een verhaal van mijn derde project met goedkope gyro en Arduino.Na de eerdere twee projecten, Gemakkelijk omgekeerd slinger en 3D kalligrafie, ik gedacht heb van het maken van Camera Gimbal met Arduino. Dan had ik drie beleidsregels voor het p
Het maken van een hart ($) gevormd geld Clip in Blender

Het maken van een hart ($) gevormd geld Clip in Blender

Hallo iedereen, je kent mij vanaf mijn animatronic creaties zoals johnny 5, robot tanks en Wall-E.Vandaag, ga ik u tonen hoe te een hartvormige geld clip maken in de blender.Hier is een link naar de mix bestand https://dl.dropboxusercontent.com/u/187
Het maken van een Nintendo SNES-controller in bluetooth; met behulp van een MSI-BGP100

Het maken van een Nintendo SNES-controller in bluetooth; met behulp van een MSI-BGP100

als, zoals velen, u de BGP100 bluetooth gadget wilt voor het spelen van bluetooth op smartphones en PDA's, maar houd niet van de knoppen en het gevoel van de domeincontroller die wordt geleverd met het, hoe zit de herhuisvesting van de controller in
Flip Top fles dop. Het maken van een duurzaam en sterk fles dop voor elke fles wijn of bier.

Flip Top fles dop. Het maken van een duurzaam en sterk fles dop voor elke fles wijn of bier.

Waarschuwing: Dit ondoorgrondelijke is een work in progress. Heeft behoefte aan een heleboel werk.Met deze kroonkurk kunt u elke fles of pot die u wilt sluiten.Je moet.Een fles met een rand in de buurt van de monding van de nek. (Wijn en bier flessen
Lessen in het maken van een middeleeuwse Vielle

Lessen in het maken van een middeleeuwse Vielle

Dit is mijn replica van een middeleeuwse vielle, een voorouder van de moderne viool. Het werd gespeeld door troubadours uit de 13e tot de 15e eeuw.Dit is niet bedoeld als een complete gids voor het maken van een vielle, noch mijn vielle bijzonder aut
Eenvoudige metaalbewerking technieken en het maken van een vlinder staal

Eenvoudige metaalbewerking technieken en het maken van een vlinder staal

Blacksmithing en traditionele metaalbewerking zijn oude ambachten en technieken die snel uit de samenleving verdwijnen. Sommige van die eenvoudige-keer vreugde te herwinnen door te leren hoe om dingen met een hamer en aambeeld te maken! Creativiteit
Van het scherm voor mij: het maken van een prop

Van het scherm voor mij: het maken van een prop

In dit, mijn eerste instructible, ik in detail te beschrijven hoe ik (met hulp) een variatie op een prop van de BBC-show Torchwood gemaakt.  De prop in kwestie is de "Vortex Manipulator" gevonden op de pols van Captain Jack Harkness.  Hieronder