Mein erstes Raycasting

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

Kabelbinder

Sieger des WM-Contest 2006

Betreff: Mein erstes Raycasting

BeitragDo, Dez 22, 2005 23:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Ist irgendwie komisch, wie sich die Dinge manchmal so ergeben:

Ich hab vor ner Zeit hier mal in einem Thread einen Link zu einer Seite gefunden, die wohl sein Jahren nicht mehr aktualisiert wurde und da stand irgendsowas, wie:
"Mit Blitzbasic kann man noch keine 3D Spiele machen, höchstens Raycasting oder Isometrie"

Ich hab von diesem Raycasting vorher noch nie was gehört und das deshalb mal bei Wikipedia nachgeschlagen. Hab rausgefunden: "Wunderbar, damit kann man also 3D Korridore erstellen" und weil ich zuvor noch gar keine Ahnung hatte, wie man überhaupt dreidimensionale sachen auf dem Bildschirm darstellen kann und mich das interessiert hat, hab ich mich mal damit beschäftigt und dashier ist rausgekommen:
Code: [AUSKLAPPEN]
AppTitle "Raycasting"
Graphics 640,680,16,2
SetBuffer BackBuffer()

Const w = 7
Const h = 7
Const plane_w = 320
Const plane_h = 240
Const view_arc = 60
Const view_w = 500

Global xcor#,ycor#,rot,divisor,distance#,st,togo,mx,my

Dim map(7,7)
For y = 0 To 7
For x = 0 To 7
Read map(x,y)
Next
Next
Data 1,1,1,1,1,1,1,1
Data 1,0,1,0,0,0,0,1
Data 1,0,1,0,0,0,0,1
Data 1,0,1,0,1,0,1,1
Data 1,0,1,1,1,0,0,1
Data 1,0,0,0,1,1,0,1
Data 1,0,1,0,0,0,0,1
Data 1,1,1,1,1,1,1,1

xcor = 75
ycor = 125
rot = 90
divisor = view_arc/plane_w

;For i = 0 To 2000
;If coll((xcor+Cos(rot)*i),(ycor+Sin(rot)*i)) Then
;distance = i
;Exit
;EndIf
;Next

distance = (1/Tan(30))*120

;st = 0
;For f# = 0.0 To 60.0 Step 0.1875
;togo = 1
;For g = 0 To view_w
;If togo = 1
;If coll(xcor+Cos(rot-30+f)*g,ycor+Sin(rot-30+f)*g) Then
;Color g,g,g
;Rect st+150,150,1,240
;DebugLog g
;togo = 0
;EndIf
;EndIf
;Next
;st = st + 1
;Next

Function coll(x,y)
If RectsOverlap(x,y,1,1,0,0,(w+1)*50,(h+1)*50) Then
If map(x/50,y/50)=1 Then Return 1
EndIf
End Function

Function move()
If KeyDown(208)=1 Then
xcor = xcor - Cos(rot)
If coll(xcor,ycor) Then xcor = xcor + Cos(rot)
ycor = ycor - Sin(rot)
If coll(xcor,ycor) Then ycor = ycor + Sin(rot)
EndIf
If KeyDown(200)=1 Then
xcor = xcor + Cos(rot)
If coll(xcor,ycor) Then xcor = xcor - Cos(rot)
ycor = ycor + Sin(rot)
If coll(xcor,ycor) Then ycor = ycor - Sin(rot)
EndIf

If KeyDown(203) Then
rot = rot - 1
EndIf
If KeyDown(205) Then
rot = rot + 1
EndIf

If rot > 360 Then rot = 0
If rot < 0 Then rot = 360

End Function

Repeat
mx = MouseX()
my = MouseY()

st = 0
For f# = 0.0 To 60.0 Step 0.1875
togo = 1
For g = 0 To view_w
If togo = 1
If coll(xcor+Cos(rot-30+f)*g,ycor+Sin(rot-30+f)*g) Then
If g > 20 Then
Color 255/(g/20),255/(g/20),255/(g/20)
Else
Color 255,255,255
EndIf

Rect st+150,150+(240-distance/g*120),1,distance/g*240
;DebugLog g
togo = 0
g = view_w
EndIf
EndIf
Next
st = st + 1
Next

move()

For y = 0 To 7
For x = 0 To 7
Color 255,255,255
If map(x,y)=1 Then
Rect x*20,y*20,20,20
EndIf
;Color 0,0,0
;Rect x*2,y*2,2,2,0
Next
Next

Color 255,0,0
Oval xcor/2.5-2,ycor/2.5-2,5,5
Line xcor/2.5,ycor/2.5,xcor/2.5+Cos(rot)*10,ycor/2.5+Sin(rot)*10
;Plot xcor/50,ycor/50

Text 200,0,distance
Text 200,10,xcor
Text 200,20,ycor
Text 200,30,st
Text 200,40,togo
Text 200,50,rot
Text 200,60,Str$(mx)+" "+Str$(my)

Flip
Cls
Until KeyHit(1)
End


Also theoretisch könnte ich jetzt Macrophage in 3D nachprogrammieren Smile
<Wing Avenger Download> ◊◊◊ <Macrophage Download>

Ironstorm

Erstklassiger Contest-Veranstalter

BeitragFr, Dez 23, 2005 1:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Also, ist nicht schlecht, aber man bewegt sich nsehr lllllaaaaannnnnggggsssaaaammmm *einschlaf*!

Aber für dein erstes Raycasting ist es echt gut.

Blitzmaker
..:: blackbird design : blackbird photography : Futuro Verde : X-Commander ::..
MacBook | Intel Core 2 Duo 2,1 GHz | 2048 MB RAM | 80 GB HDD | Mac OS X 10.6.2 (Snow Leopard) | Adobe CS4 Design Premium

hectic

Sieger des IS Talentwettbewerb 2006

BeitragFr, Dez 23, 2005 2:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Wow,.. Auch noch wenig Code und nicht so überladen mit sinnlosen Funktionen. Und, du hast die Entfernung radial ausgestreckt, nicht wie es die meisten machen linear. Der Vorteil dieses Verfahrens ist ja, daß eine art Linseneffekt auftritt. Der ja realistisch ist und bei herkömlicher 3D-Darstellung nicht vorkommt.

maximilian

BeitragFr, Dez 23, 2005 2:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Das größte Problem bisj jetzt ist wohl dieser Fish-Bowl-Effekt. Probiere den wegzubekommen und es sieht sehr viel besser aus. Smile
Variety is the spice of life. One day ignore people, next day annoy them.

hectic

Sieger des IS Talentwettbewerb 2006

BeitragFr, Dez 23, 2005 4:01
Antworten mit Zitat
Benutzer-Profile anzeigen
@LordChaos, der Fish-Effekt ist doch eigendlich das coole daran. Das kommt daher das der Ray sich radial vom Betrachter entfernt. Dieser Effekt ist soweit auch realistisch! Kommt beispielsweise ganz stark bei Weitwinkelobjektiv oder Panoramaaufnahmen vor. Bei einer normalen Kamera sieht man den Effekt nicht so stark, da diese nur einen kleinen Teil des ganzen einfangen. Diesen Effekt kann man leicht durch eine parallele Ausbreitung des Rays unterbinden, aber dann kann man ja auch gleich mit der 3D-Unterstützung von DirectX/OpenGL usw. weiter machen.

Da ich mal wieder nicht die Finger lassen konnte... Hier mal meine Version eines Raycasters. Mit Cursor Bewegen. Mit Maus hoch/runter/links/rechts schauen. Mit 1 und 2 kann man den Sichtbereich einstellen...

Code: [AUSKLAPPEN]
Graphics 400,400,0,2
SetBuffer BackBuffer()
Origin 200,200
HidePointer

Dim xy(9,9) ;Spielfeld
xp#=1 ;Spieler-X-Position
yp#=1 ;Spieler-Y-Position
ws#=90 ;SPieler-Sollwinkel
wi#=90 ;Spieler-Istwinkel
hs#=0 ;Spieler-Sollhöhe
hi#=0 ;Spieler-Isthöhe
x#=0 ;Schleifenvariable
y#=0 ;Schleifenvariable
e#=0 ;Strahlentfernung zur Wand
w%=6 ;wsnkeleinfang (tele/weit)
f%=0 ;Funktionsvariable

For y=0 To 9
 For x=0 To 9
  Read xy(x,y)
 Next
Next

Data 1,1,1,1,1,1,1,1,1,1
Data 1,0,1,0,0,0,0,0,0,1
Data 1,0,1,0,1,0,1,0,0,1
Data 1,0,0,0,1,0,0,0,0,1
Data 1,0,1,1,1,0,1,0,0,1
Data 1,0,1,0,0,0,0,0,0,1
Data 1,0,1,0,0,0,0,0,0,1
Data 1,0,1,1,1,1,1,1,0,1
Data 1,0,0,0,0,0,0,0,0,1
Data 1,1,1,1,1,1,1,1,1,1




;Hauptschleife
While Not KeyHit(1)

 ;Kopfbewegung
 ws=(ws+MouseXSpeed())/1.4
 hs=(hs+MouseYSpeed())/1.4
 wi=wi+ws/20
 hi=hi-hs/5
 MoveMouse 200,200
 If hi<-160 Then hi=-160
 If hi>160 Then hi=160

 ;Körperbewegung
 If KeyDown(203) Then wi=wi-16/w
 If KeyDown(205) Then wi=wi+16/w
 If KeyDown(200) Then If xy(xp+Cos(wi)/24,yp+Sin(wi)/24)=0 Then xp=xp+Cos(wi)/24:yp=yp+Sin(wi)/24
 If KeyDown(208) Then If xy(xp-Cos(wi)/24,yp-Sin(wi)/24)=0 Then xp=xp-Cos(wi)/24:yp=yp-Sin(wi)/24
 If MouseDown(2) Then If xy(xp+Cos(wi)/24,yp+Sin(wi)/24)=0 Then xp=xp+Cos(wi)/24:yp=yp+Sin(wi)/24
 If KeyHit(2) Then w=w-1:If w<1 Then w=1
 If KeyHit(3) Then w=w+1:If w>8 Then w=8

 ;Raycaster
 For x=-200 To 200 Step 2
  f=0
  For e=0 To 5 Step .02
   If f=0 And xy(xp+Cos(wi+x/w)*e,yp+Sin(wi+x/w)*e)=1 Then
    Color 255-e*50,255-e*50,255-e*50
    Rect x,hi-200/e,2,400/e
    f=1
   End If
  Next
 Next

 ;Map zeichnen
 Color 0,0,0
 Rect -200,-200,80,80,1
 Color 240,240,240
 For y=0 To 9
  For x=0 To 9
   If xy(x,y)=1 Then Rect x*8-200,y*8-200,8,8,1
  Next
 Next
 Rect xp*8-197.5,yp*8-197.5,3,3,1
 Line xp*8-196.5,yp*8-196.5,xp*8-196.5+Cos(wi)*4,yp*8-196.5+Sin(wi)*4

 Flip
 Cls
Wend
End


/EDIT: Habs leider mit der Kollision nicht so gut hinbekommen. Bei einer Wandkollision bleibt mein Männchen stehen. Sad

maximilian

BeitragFr, Dez 23, 2005 12:17
Antworten mit Zitat
Benutzer-Profile anzeigen
So, jetzt fehlt nurnoch Texture-Mapping. Sollte auch ziemlich einfach zu implementieren sein. Smile
Variety is the spice of life. One day ignore people, next day annoy them.
 

#Reaper

Newsposter

BeitragFr, Dez 23, 2005 12:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Also das sieht doch echt mal toll aus Smile Very Happy
Würde sowas wohl nicht hinbekommen Wink

Allerdings, finde ich das mit dem Fischauge etwas..unrealistisch.also, vielleicht seh ich ja auch nicht richtig, aber zumindestens sieht das nicht so stark aus Wink
Okok...ich versteh davon eh nicht viel..fas nichts ^^

Nur weiter so Very Happy

MfG
#Reaper
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7

Kabelbinder

Sieger des WM-Contest 2006

BeitragDi, Dez 27, 2005 17:58
Antworten mit Zitat
Benutzer-Profile anzeigen
hm, bisher konnte ich den Linseneffekt nur minimieren:
Code: [AUSKLAPPEN]
AppTitle "Raycasting"
Graphics 850,680,16,2
SetBuffer BackBuffer()

Const w = 7
Const h = 7
Const view_arc# = 100
Const view_w = 255
Const quality = 2
Const width_fac# = 0.21

Global xcor#,ycor#,rot,distance#,st,togo,mx,my,speed

Dim map(7,7)
For y = 0 To 7
For x = 0 To 7
Read map(x,y)
Next
Next
Data 1,1,1,1,1,1,1,1
Data 1,0,1,0,0,0,0,1
Data 1,0,1,0,0,0,0,1
Data 1,0,1,0,1,0,1,1
Data 1,0,1,1,1,0,0,1
Data 1,0,0,0,1,1,0,1
Data 1,0,1,0,0,0,0,1
Data 1,1,1,1,1,1,1,1

xcor = 75
ycor = 125
rot = 90
speed = 2

distance = (1/Tan(view_arc/2))*120

Function coll(x,y)
If RectsOverlap(x,y,1,1,0,0,(w+1)*50,(h+1)*50) Then
If map(x/50,y/50)=1 Then Return 1
EndIf
End Function

Function move()
If KeyDown(208)=1 Then
xcor = xcor - Cos(rot) *speed
If coll(xcor,ycor) Then xcor = xcor + Cos(rot)*speed
ycor = ycor - Sin(rot) *speed
If coll(xcor,ycor) Then ycor = ycor + Sin(rot) *speed
EndIf
If KeyDown(200)=1 Then
xcor = xcor + Cos(rot) *speed
If coll(xcor,ycor) Then xcor = xcor - Cos(rot) *speed
ycor = ycor + Sin(rot) *speed
If coll(xcor,ycor) Then ycor = ycor - Sin(rot) *speed
EndIf

If KeyDown(203) Then
rot = rot - 1 *speed
EndIf
If KeyDown(205) Then
rot = rot + 1 *speed
EndIf

If rot > 360 Then rot = 0
If rot < 0 Then rot = 360

End Function

Repeat
mx = MouseX()
my = MouseY()

st = 0
For f# = 0.0 To view_arc Step width_fac#
togo = 1
For g = 0 To view_w Step quality
If togo = 1
If coll(xcor+Cos(rot-view_arc/2+f)*g,ycor+Sin(rot-view_arc/2+f)*g) Then
If g <= 255 Then
Color -g+255,-g+255,-g+255
Else
Color 0,0,0
EndIf

Rect st+150,150+(240-distance/g*120),1,distance/g*240
togo = 0
g = view_w
EndIf
EndIf
Next
st = st + 1
Next

Color 0,0,0
Rect 0,0,850,150
Rect 0,480+150,850,680
Rect 0,0,150,680
Rect 150+666,0,150,680

move()

For y = 0 To 7
For x = 0 To 7
Color 255,255,255
If map(x,y)=1 Then
Rect x*20,y*20,20,20
EndIf
Next
Next

Color 255,0,0
Oval xcor/2.5-2,ycor/2.5-2,5,5
Line xcor/2.5,ycor/2.5,xcor/2.5+Cos(rot)*10,ycor/2.5+Sin(rot)*10

Text 200,0,distance
Text 200,10,xcor
Text 200,20,ycor
Text 200,30,st
Text 200,40,togo
Text 200,50,rot
Text 200,60,Str$(mx)+" "+Str$(my)

Flip
Cls
Until KeyHit(1)
End


Ich hab die Brennweite verändert und einen Rahmen um die ganze Geschichte gemacht. Ich glaube, das liegt einfach an der Methode, die ich benutze, nach der ist das ganz gut nachvollziehbar mit dem Linseneffekt. Ich weiß auch nicht, wie ich den Effekt ganz wegbekommen kann.
Läuft jetzt auch schneller

Im Moment versuche ich das zu texturieren, was ich wohl nie hinkriegen werde
<Wing Avenger Download> ◊◊◊ <Macrophage Download>
 

FWeinb

ehemals "ich"

BeitragSa, Dez 31, 2005 12:13
Antworten mit Zitat
Benutzer-Profile anzeigen
seit super aus aber Shocked



könte einer bitte bitte bitte den code kommentieren

hectic

Sieger des IS Talentwettbewerb 2006

BeitragSa, Dez 31, 2005 19:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo ich Rolling Eyes , hier mal eine dokumentierte Version... Dachte eigentlich das so wenig Code leicht verständlich währe.Code: [AUSKLAPPEN]
;Bildschirmauflösung setzen
Graphics 320,240,32,1
;Bildschirmzwischenpuffer einschalten
SetBuffer BackBuffer()
;X/Y-Koordinaten auf Bildschirmmitte verlagern
Origin 160,120
;Mauspointer versteken (nur bei Fenstermodus)
HidePointer

Dim xy(19,19) ;Spielfeld
xp#=1 ;Spieler-X-Position
yp#=1 ;Spieler-Y-Position
ws#=90 ;SPieler-Sollwinkel
wi#=90 ;Spieler-Istwinkel
hs#=0 ;Spieler-Sollhöhe
hi#=0 ;Spieler-Isthöhe
x#=0 ;Schleifenvariable
y#=0 ;Schleifenvariable
e#=0 ;Strahlentfernung zur Wand
w%=3 ;Winkeleinfang (tele/weit)
f%=0 ;Funktionsvariable

;Hier wird die Map in die DIM-Felder eingelesen
For y=0 To 19
 For x=0 To 19
  ;Datafelder nacheinander auslesen und positioniert in das Dim eintragen
  Read xy(x,y)
 Next
Next

;Die Map, 0=frei, 1=Wand
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,0,0,1
Data 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1
Data 1,0,1,1,1,1,1,0,1,0,0,0,0,0,0,0,1,0,1,1
Data 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1
Data 1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,1,1
Data 1,0,1,0,1,0,0,0,0,0,0,1,0,1,0,0,0,1,1,1
Data 1,0,0,0,1,0,1,0,1,0,1,1,0,1,1,0,0,0,0,1
Data 1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1
Data 1,0,0,0,0,0,1,0,1,0,1,1,0,1,1,0,0,0,0,1
Data 1,0,1,1,1,1,1,0,0,0,0,1,0,1,0,0,0,1,1,1
Data 1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,1,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0,1
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1




;HAUPTSCHLEIFE
While Not KeyHit(1)

 ;KOPFBEWEGUNG
 ;WS ist der Sollwinkel (Laufrichtung) der durch eine Maus-X-Bewegung berechnet wird.
 ws=(ws+MouseXSpeed())/1.4
 ;HS ist die Sollbetrachtungshöhe (Kopf hoch/runter) der durch eine Maus-Y-Bewegung berechnet wird.
 hs=(hs+MouseYSpeed())/1.4
 ;Damit die Bewegungen nicht zu 'hackelig' wird, wird eine Annäherung zum Sollwinkel berechnet.
 ;WI ist der Istwinkel (Laufrichtung) der sich an den Sollwinkel annährt.
 wi=wi+ws/3/w
 ;HI ist die Istbetrachtungshöhe (Kopf hoch/runter) der sich an die Sollhöhe annährt.
 hi=hi-hs/5
 ;Da die Mausabfrage nur relativ genutzt wird (erst damit wird es möglich sich öffters umrum zu
 ;drehen, da die Maus jetzt keine Begrenzug mehr kennt) muß die Maus zur Bildschirmmitte bewegt werden.
 MoveMouse 160,120
 ;Damit die Kopfhöhe keinen Nackenbruch des Spielers hervorruft wird die Betrachtungshöhe eingegrenzt.
 If hi<-80 Then hi=-80
 If hi>80 Then hi=80

 ;KÖRPERBEWEGUNG
 ;Wenn [Strg] gedrückt (nach links sliden) dann soll überprüft werden ob es überhaupt geht. Dies wird durch
 ;eine umgerechnete 'Kollisionsprüfung' auf dem Dim-feld direkt geacht. Ist das Feld frei dann wird bewegt.
 If KeyDown(29) Then If xy(xp-Cos(wi+90)/48,yp-Sin(wi+90)/48)=0 Then xp=xp-Cos(wi+90)/48:yp=yp-Sin(wi+90)/48
 ;Wenn [linke Alt] gedrückt (nach rechts sliden) dann wird das gleiche gemacht wie bei [Strg] nur nach rechts.
 If KeyDown(56) Then If xy(xp-Cos(wi-90)/48,yp-Sin(wi-90)/48)=0 Then xp=xp-Cos(wi-90)/48:yp=yp-Sin(wi-90)/48
 ;Wenn [q] gedrückt (nach hinten laufen) dann wird das gleiche gamcht wie bei [Strg], [linke Alt] nur nach hinten.
 If KeyDown(16) Then If xy(xp-Cos(wi)/24,yp-Sin(wi)/24)=0 Then xp=xp-Cos(wi)/24:yp=yp-Sin(wi)/24
 ;Wenn [rechte Maustaste] gedrückt (nach vorne laufen) dann wird das gleiche gamcht wie bei den anderen nur nach vorne.
 If MouseDown(2) Then If xy(xp+Cos(wi)/24,yp+Sin(wi)/24)=0 Then xp=xp+Cos(wi)/24:yp=yp+Sin(wi)/24
 ;Wenn [1] gedrückt wird der Bildeinfangwinkel/Betrachtungswinkel vergrössert (ähnlich einem Weitwinkelobjektiv).
 If KeyHit(2) Then w=w-1:If w<1 Then w=1
 ;Wenn [2] gedrückt wird der Bildeinfangwinkel/Betrachtungswinkel verkleiner (ähnlich einem Teleobjektiv).
 If KeyHit(3) Then w=w+1:If w>6 Then w=6

 ;RAYCASTER
 ;Die X/Y-Koordinaten sind durch Origin 160,120 zum Bildschirmmitte verlagert worden.
 ;Jede zweite Bildschirmzeile von links nach rechts durchgehen X-Variable.
 For x=-160 To 160 Step 2
  ;F ist eine Hilfsvariable die die Darstellung erheblich schneller macht. Sie ermöglicht es sinnlose
  ;überprüfungen (Rechenaufwendig) zu vermeiden.
  f=0
  ;E ist die Entfernung die der Ray hinterlegen muß, bis es auf eine Wand (Dim xy(xx,yy)) trifft.
  For e=0 To 26 Step .04
   ;Nur so lange weiterprüfen wenn der aktuelle Ray noch keine Wand 'getroffen' hat.
   If f=0 Then
    ;Überprüfen ob neue berechnete Position des Ray's auf eine wand trifft.
    If xy(xp+Cos(wi+x/w)*e,yp+Sin(wi+x/w)*e)=1 Then
     ;Ray hat jetzt eine Wand getroffen. Aufgrund der Entfernung E wird
     ;jetzt der Farbwerd der Wand an dieser Stelle berechnet.
     Color 512/(e+2),1024/(e+4),512/(e+2);255-e*9
     ;Die neu berechnete Wand wird entsprechend der Entfernung E in einer berechneten 'größe' dargestellt.
     Rect x,hi-100/e,2,200/e
     ;Der Ray hat eine Wand getroffen, weitere Berechnungen werden für diesen Ray hiermit unterbunden.
     f=1
    End If
   End If
  Next
 Next

 ;FADENKREUZ
 ;Zeichnet das Fadenkreuz ein
 Color 255,255,255:Rect -1,-1,2,2,1

 ;Damit V-Sync immer 'erzwungen' wird. Auch dann wenn der User
 ;der Meinung ist er müsse das Treiberseitig ausschalten. :-)
 VWait
 ;Bildschirm anzeigen. Bitte immer 0, da bereits VWait aktiviert!
 Flip 0
 ;Bildschirm für neue Ausgabe löschen
 Cls
Wend
End

P.S. Ich verlange eine Antwort, ob ich dir damit helfen konnte... Smile

maximilian

BeitragMo, Jan 02, 2006 14:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Man kann durch eine weitere Formel den Fishbowl-Effekt komplett vermeiden, da ich aber von Raycasting keine Ahnung habe... Rolling Eyes
Auf QBasic.de war mal (und ist immernoch) ein enorm gutes Tutorial über die Grafikprogrammierung in QB. Da hat der Raycasting enorm gut beschrieben. Vielleicht schaust du es dir mal an, steht auch genau drin wie du diesen Effekt wegberechnen kannst. Smile
Variety is the spice of life. One day ignore people, next day annoy them.

hectic

Sieger des IS Talentwettbewerb 2006

BeitragMo, Jan 02, 2006 15:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Also noch einmal... Warum sollte man etwas schlechter und dabei auch noch aufwendiger machen als man es bereits fertig hat? Dieser Effekt kommt übrigens immer vor! Es ist schlicht unmöglch 'richtiges 3D' darzustellen und auf ein solchen Effekt zu verzichten. Dieser Effekt kommt bei Fotografien, Kameraaufnahmen, dem Menschlichem Auge etc. praktisch überall vor wo die 3D-Welt auf eine flache 2D-Darstellung abgelichtet wird (Beim Auge ist der Effekt wiederrum nicht so stark, da die Netzhaut bereits auch gewölbt ist, aber nicht so stark wie der Betrachtungswinkeleinfang des Auges.). Bei normalen Aufnahmen sieht man es nicht so stark, da Fehrnsehshows, Nachrichten etc nur einen sehr kleinen Teil der Vollaufnahme einfangen. Also je mehr Weitwinkel um so mehr Fishauge-Effekt. Bei Panoramaaufnahmen kommt der Effekt noch mehr zu tragen, und da würde keiner sagen "Das hat man mit dem Computer extra so gemacht damit der Betrachter verwirrt ist". Mir ist klar das ein Raycaster (also eine umgerechete 2D-Grafik) nur in der Y-Achse die Verzehrung hat. Bei richigen Renderprogrammen (Raytracer) wird auch die X-Achse verzehrt. Eine solche Darstellung währe aber in Realtime noch nicht möglich und erst recht nicht unter BB.

Um den Effekt komplett bei einem Raycaster zu vermeiden müsste man die 'Strahlen' nicht radial sondern parallel ausbreiten. Die Entfernung zu Objekten währe dann am Rande des Bildschirmes weiter weg als in der Mitte, würden aber fälschlicherweise gleih nah gezeichnet.

Übrigens: Das was die Grafikkarten bei HalfLife1+2, Doom3, etc darstellen, ist weniger richtiges 3D als die Versuche hier! Doom1+2, Heretic, Duke Nukem etc wahren alle Raycaster aber mit paralleler Ausbreitung der Strahlen. Warum die das so gemacht haben weiß ich nicht. Vielleicht habe sie gesehen das viele damit nicht klar kommen. Oder vielleicht weil sonst die Texturen nicht mehr so 'einfach' auf die Welt projeziert werden kann.

Könnte mich mal in den nächsten Tagen hinsetzen und ein solchen programmieren.
 

Apocalyptic

BeitragMo, Jan 02, 2006 17:13
Antworten mit Zitat
Benutzer-Profile anzeigen
@Hectic: Der Fischaugen-Effekt mag zwar rein theoretisch realistisch sein - aber wenn du die Welt mit deinen Augen so war nimmst, tust du mir Leid Wink
Es ist schlicht weg Fakt, dass unser Auge unsere Umgebung nicht derart verzerrt wahrnimmt. Das dürfte wohl auch der Grund sein, warum Doom1+2, Heretic, Duke Nukem etc. den Fischaugen-Effekt vermeiden - der Spieler läuft eben nicht mit einem Fischaugenobjektiv vor den Augen rum Wink

@Kabelbinder: Netter Anfang. Wenn du den Fischaugen-Effekt nicht so verehrst wie Hectic, reicht es, wenn du anstatt der realen Entfernung, welche die Hypothenuse c des folgenden Dreiecks darstellt, die Ankathete a für die Berechnung der Höhe einer Wand nimmst:

user posted image
Diese lässt sich mit einfachsten trigonometrischen Kenntnissen aus der Hypothenuse berechnen Smile
Suum cuique

[ www.ffs-net.de.vu ] [ Raycaster ]

hectic

Sieger des IS Talentwettbewerb 2006

BeitragMo, Jan 02, 2006 23:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Apocalyptic, das menschliche Auge nimmt diesen Effekt aus zwei Gründen nicht so stark war wie das eines Weitwinkelobjektives. 1) Das Gehirn 'richtet' die Krümmung um geraden besser ausfindig zu machen. 2) Weil die Netzhaut im inneren des Auges auch eine Krümmung hat (ist ja nicht platt). Beim ersteren kann man dies am besten erkennen wenn man sich in einer nicht gewöhnlichen Situation befindet. Beispiel: Man lege sich in die Mitte eines Zimmers und schaut gerade nach oben, so das man alle vier Wände sehen kann. Die Kanten an der Decke erscheinen dann auch gewölbt.

Wer denoch ein Raycaster mit geraden haben will nimmt sich mein letzten oben geposteten Code und ersetzt die Zeile 102 durch folgende.Code: [AUSKLAPPEN]
     If xy(xp+(Cos(wi)*e)+Cos(90+wi)*(e*x/100),yp+(Sin(wi)*e)+Sin(90+wi)*(e*x/100))=1 Then
 

Apocalyptic

BeitragDi, Jan 03, 2006 3:07
Antworten mit Zitat
Benutzer-Profile anzeigen
hectic hat Folgendes geschrieben:
1) Das Gehirn 'richtet' die Krümmung um geraden besser ausfindig zu machen. 2) Weil die Netzhaut im inneren des Auges auch eine Krümmung hat (ist ja nicht platt).


Richtig. Das führt dazu, dass, wenn du senkrecht auf eine Wand siehst, diese nicht derart gekrümmt wahrnimmst:

user posted image

Wieso sollte dieses Verhalten der menschlichen Wahrnehmung dann bei einem Raycaster nicht nachempfunden werden, wenn diese "Korrekturen", die der Mensch mehr als nur gewohnt ist, bei der Darstellung eines dreidimensionalen Raumes auf einem flachen Bildschirm nicht funktionieren?
Suum cuique

[ www.ffs-net.de.vu ] [ Raycaster ]

hectic

Sieger des IS Talentwettbewerb 2006

BeitragDi, Jan 03, 2006 4:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Weil das menschliche Auge in der realen Welt diese Korekturen vornimmt, aber die Linse eines Weitwinkelobjektives nicht und somit die Darstellung der realen Welt auf ein flachen Bildschirm genauso verzehrt am 'richtigsten' ist. Wenn ich vor einer Mauer stehe sehe ich die Verzehrung nicht besonders (weil das Gehirn es für mich überarbeitet hat, sonst könnten wir einen geraden Masst nicht von einem gekrümten Baum unterscheiden). Wenn man sich nicht grad dumm anstellt, kann man auch mit sturem Geradeausblick auf eine Mauer beide Fluchtpunkte gleichzeitig sehen. Das nachahmen der beiden Fluchtpunkten wird erst in einem Raycaster möglich. Ich muß mich nicht mit der Maus umschauen um den einen oder anderen Fluchtpunkt zu sehen, sondern es reicht wenn ich mein Auge an den Seiten meines Spiels richte. Letztendlich bleibt es jedem selbst überlassen. Ich zu meinem Teil würde am liebsten HalfLife2 mit einer Raytracer-Engine spielen, was wohl noch an der Performance schrauben dürfte. Alle mir bekannten Egoshoter haben 90° (+-45° in der X-Achse) Blickeinfang. Erst mit einem Raycaster sind 180° und mehr möglich. Perfekt währe das spielen eines solchen Spiels dann erst vor einer Leinwand die bereits fast den ganzen Sichtbereich des Auges abdeckt. Aber für die die es nicht so gern haben, habe ich mein letzten Post geschrieben. Gerade Linien auf einem Raycaster. Dann kann man lieber gleich auf die 3D-Unterstützung der Grafikkarten zurrückgreifen. Ein weiteres Problem bei der Hardware unterstützten Darstellung ist, daß Gegenstände am Rande des Bildschirmes fast doppelt so tief wirken als sie es sind. Das passiert bei einem Raycaster nicht.

werde mal zum Spaß noch einen Raytracer schreiben. Allerdings nicht auf Vektorbasis sondern per 3D-Dim-Felder. Mal sehen wie das dann aussieht.

Kabelbinder

Sieger des WM-Contest 2006

BeitragMi, Jan 04, 2006 16:54
Antworten mit Zitat
Benutzer-Profile anzeigen
thx, Apocalyptic. könnte man sich nicht vielleicht auch senkrecht zur blitzrichtung bewegen und jeden Pixel einen Strahl werfen?
dann müsste man doch auch so Gerade Kanten herausbekommen.

Ich hab jetzt den Linseneffekt eigentlich raus, dafür tritt jetzt aber eine Art Klopapiereffekt auf Laughing

Code: [AUSKLAPPEN]
AppTitle "Raycasting"
Graphics 850,680,16,2
SetBuffer BackBuffer()

Const w = 7
Const h = 7
Const view_arc# = 100
Const view_w = 255
Const quality = 2
Const width_fac# = 0.21

Global xcor#,ycor#,rot,distance#,st,togo,mx,my,speed,textur

;textur = LoadImage("Bild/Tex2.bmp")
;Dim wall(320)
;For i = 1 To 320 Step 3
;wall(i)=CopyImage(textur)
;ResizeImage(wall(i),i,i)
;wall(i+1)=wall(i)
;wall(i+2)=wall(i)
;Print i
;Next

Dim map(7,7)
For y = 0 To 7
For x = 0 To 7
Read map(x,y)
Next
Next
Data 1,1,1,1,1,1,1,1
Data 1,0,1,0,0,0,0,1
Data 1,0,1,0,0,0,0,1
Data 1,0,1,0,1,0,1,1
Data 1,0,1,1,1,0,0,1
Data 1,0,0,0,1,1,0,1
Data 1,0,1,0,0,0,0,1
Data 1,1,1,1,1,1,1,1

xcor = 75
ycor = 125
rot = 90
speed = 2

distance = (1/Tan(view_arc/2))*120

Function coll(x,y)
If RectsOverlap(x,y,1,1,0,0,(w+1)*50,(h+1)*50) Then
If map(x/50,y/50)=1 Then Return 1
EndIf
End Function

Function move()
If KeyDown(208)=1 Then
xcor = xcor - Cos(rot) *speed
If coll(xcor,ycor) Then xcor = xcor + Cos(rot)*speed
ycor = ycor - Sin(rot) *speed
If coll(xcor,ycor) Then ycor = ycor + Sin(rot) *speed
EndIf
If KeyDown(200)=1 Then
xcor = xcor + Cos(rot) *speed
If coll(xcor,ycor) Then xcor = xcor - Cos(rot) *speed
ycor = ycor + Sin(rot) *speed
If coll(xcor,ycor) Then ycor = ycor - Sin(rot) *speed
EndIf

If KeyDown(203) Then
rot = rot - 1 *speed
EndIf
If KeyDown(205) Then
rot = rot + 1 *speed
EndIf

If rot > 360 Then rot = 0
If rot < 0 Then rot = 360

End Function

Repeat
mx = MouseX()
my = MouseY()

st = 0
For f# = 0.0 To view_arc Step width_fac#
togo = 1
For g = 0 To view_w Step quality
If togo = 1
If coll(xcor+Cos(rot-view_arc/2+f)*g,ycor+Sin(rot-view_arc/2+f)*g) Then
If g <= 255 Then
Color -g+255,-g+255,-g+255
Else
Color 0,0,0
EndIf

Rect st+150,150+80000.0/Float(480+Cos(view_arc/2)*g),1,80000.0/Float(480+Cos(view_arc/2)*g)
togo = 0
g = view_w
EndIf
EndIf
Next
st = st + 1
Next

Color 0,0,0
Rect 0,0,850,150
Rect 0,480+150,850,680
Rect 0,0,150,680
Rect 150+666,0,150,680

move()

For y = 0 To 7
For x = 0 To 7
Color 255,255,255
If map(x,y)=1 Then
Rect x*20,y*20,20,20
EndIf
Next
Next

Color 255,0,0
Oval xcor/2.5-2,ycor/2.5-2,5,5
Line xcor/2.5,ycor/2.5,xcor/2.5+Cos(rot)*10,ycor/2.5+Sin(rot)*10

Text 200,0,distance
Text 200,10,xcor
Text 200,20,ycor
Text 200,30,st
Text 200,40,togo
Text 200,50,rot
Text 200,60,Str$(mx)+" "+Str$(my)

Flip
Cls
Until KeyHit(1)
End
<Wing Avenger Download> ◊◊◊ <Macrophage Download>
 

Apocalyptic

BeitragDo, Jan 05, 2006 16:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Kabelbinder hat Folgendes geschrieben:
könnte man sich nicht vielleicht auch senkrecht zur blitzrichtung bewegen und jeden Pixel einen Strahl werfen?

Blitzrichtung? o_O


Kabelbinder hat Folgendes geschrieben:
Ich hab jetzt den Linseneffekt eigentlich raus, dafür tritt jetzt aber eine Art Klopapiereffekt auf Laughing

Das hier ist auch nicht die Ankathete:Code: [AUSKLAPPEN]
Cos(view_arc/2)*g
Wink
Suum cuique

[ www.ffs-net.de.vu ] [ Raycaster ]

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group