Seite 3 von 3
Verfasst: 02.12.2005 22:32
von Kekskiller
Also... auf jeden Fall holt ihr mich gerade in den Bereich der Möglichkeiten zurück, vor allem was vorberechnen angeht. Anscheinden bin ich abgestumpft

.
@Kaeru: Falsch. Das lässt sich schlecht realisieren, da ich z.b. auch negative Gradzahlen abfrage, bzw. den normalen 0 bis 2PI-Bereich über-, oder unterschreite. In Quickbasic konnte ich das immer recht gut mi DIM(-360 TO 360) oder so erledigen, aber hier kommen für mich zuviele Umrechnungen dazu, also ein für mich momentan zu großer Aufwand (ja, ich weiß, Performace-technisch wahrscheinlich interessant auszutesten, aber es gibt auch noch andere Sachen, die ich verbessern könnte und die vorerst schneller zu realisieren sind). Aber wenn ich mir das so ansehe, ist es vielleicht gut, das später aufzugreifen.
@PI und Konstante: Das ist mir eigentlich relativ egal, da ich mit beiden Varianten keine Verbesserung des Geschwindigkeit erlangt habe. Ach übrigens rufe ich die Funktion sowieso nur in der Steuerungsschleife auf, also ist das wophl kaum das große Performance-Problem.
@AndyX: Das Tutorial kenne ich, daraus hab ich ja hier und jetzt diese "quick'n dirty"-Vorlage geschrieben, entsprechend nicht mit den Funktionen dort. Aber du hast recht, es sollte viel schneller gehen, diese Wände "anzuspringen", als dass alle selbst berechnet werden. Entweder ich baue das ganze so ein, oder ich lege einfach eine größeren Spungwert für "dist+1" ein.
@all: Wie wird das dann aber z.b. bei DOOM gemacht? Dort können auch schräge Wände benutzt werden, es wird ja kein Raster verwendet, in dass sich das ganze einpasst. Denn könnte ich auch bei meinen kleinen Maßstäben bleiben, würde aber nur kleine, miteinandergekoppelte Räume machen. Der Editor ist dafür kein Problem, schließlich kann ich das ja auch mit einfach Vektoren machen. Nur wird sich da das weiter oben angesprochene Rastersystem sich da nicht gut machen. Was ist euer Rat?
Verfasst: 02.12.2005 22:44
von Kaeru Gaman
> Aber wenn ich mir das so ansehe, ist es vielleicht gut, das später aufzugreifen.
kleiner tipp:
wenn du dein array nach einer 2er-potenz dimensionierst,
also 256,512,1024 oder 2048 für den vollkreis,
dann musst du zwar den winkel anders behandeln,
(im endeffekt nur den faktor ändern, nämlich anstatt pi/180 einfach pi/512 für 1024)
dann kann dein winkel jeden long-wert annehmen, und du greifst mit
SinArray(Winkel & 1023) darauf zu...
...warum soll denn ein vollkreis nich 1024° haben...?
alles ne frage der definition, die 360° kommen eh aus der mystik...
Verfasst: 02.12.2005 23:16
von Kekskiller
Darum gings mir in der Regel eigentlich nicht, sondern um das Umwandeln der negativen Werte. Das hatte ich schonmal in meine Spiel "Tricorne" verwendet, aber das es nicht ganz funktionierte kann man daran sehen, dass die Gegner ab und zu einfach nach unten trudelten... Aber trotzdem danke für die Info

.
Ich hab mir einfach mal die Vorberechnungen vorgenommen, und siehe da: Es funktioniert anstandslos und fix. Jetzt muss ich nur noch die Sache mit dem Sinus-Vorberechnen, aber das bekomm ich auch noch alles unter einen Hut. Ich bedanke mich für eure -wie immer- kompetente Hilfe!
Code: Alles auswählen
Global mapx.l, mapy.l, mapz.l
Global fps.l, time.l, screenDC.l
Global playerx.l, playery.l, playerz.f
Global playerfov.l, playermove.l, playerturn.l
Global screenx.l, screeny.l, screenwallfactor.l, screenx2.l, screeny2.l
Global flag_lightbreak.b
#PI = 3.141592
Procedure.f atosin(angle.w)
s.f = (#PI / 180) * angle
ProcedureReturn s
EndProcedure
;*************************
#std_wall_height_percent = 15.4167
;*************************
flag_lightbreak = #True
screenx = 320
screenx2 = screenx/2
screeny = 240
screeny2 = screeny/2
screenwallfactor = screeny + (#std_wall_height_percent / 100) * screeny
mapz = 32
mapx = 10*mapz
mapy = 10*mapz
playerx = 1*mapz
playery = 1*mapz
playerz = atosin(85)
playerfov = atosin(45)
playermove = mapz / 5
playerturn = 5
Dim map.l(mapx,mapy)
#color_wall = $999999
Procedure cast(z,distlen,correction.f);, angle.f) ;"correction" ist die korrekturvariable der perspektive
Protected pix.f, color.l
pix.f = mapz / distlen * screenwallfactor
pix.f / correction
Box(z,screeny2-Int(pix)/2, 1,Int(pix), #color_wall)
EndProcedure
Procedure render()
Protected angle.f, dist.l
Protected rx.l, ry.l, z.l
Protected pfovhalf.f, astep.f
Protected leftsidedir.f ,rightsidedir.f ;vorberechnung der gradanzahl
Protected anglesin.f, anglecos.f ;vorberechnung des sinus' und cosinus'
pfovhalf.f = playerfov / 2
astep.f = playerfov / screenx
angle = playerz - pfovhalf
For z=0 To screenx-1
angle + astep
dist=0
leftsidedir = angle - playerz ;gradanzahl für die linke seite vorberechnen...
rightsidedir = playerz - angle;gradanzahl für dierechte seite vorberechnen...
anglesin = Sin(angle)
anglecos = Cos(angle)
Repeat
dist+1
rx = playerx + anglesin * dist
ry = playery + anglecos * dist
If rx>=0 And ry>=0 And rx<mapx And ry<mapy
If map(rx,ry) = 1
If z <= screenx2 - 1
c.f = Cos(leftsidedir)
ElseIf z >= screenx2
c.f = Cos(rightsidedir)
EndIf
cast(z, dist, c.f)
Break
EndIf
Else
Break
EndIf
ForEver
Next
EndProcedure
Procedure load()
For zy=0 To mapy
For zx=0 To mapx
If zy=0 Or zy=mapx-1 Or zx=0 Or zx=mapy-1
map(zx, zy) = 1
EndIf
Next
Next
EndProcedure
load()
InitSprite()
EP_InitFXLib()
InitKeyboard()
OpenWindow(0,0,0,screenx,screeny,#PB_Window_SystemMenu, "rm3")
OpenWindowedScreen(WindowID(), 0,0, screenx,screeny, 0,0,0)
;OpenScreen(screenx,screeny,32,"rm3")
Repeat
event = WindowEvent()
ClearScreen(0,0,0)
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Left)
playerz - atosin(playerturn)
ElseIf KeyboardPushed(#PB_Key_Right)
playerz + atosin(playerturn)
EndIf
If KeyboardPushed(#PB_Key_Up)
playerx + (Sin(playerz) * playermove)
playery + (Cos(playerz) * playermove)
ElseIf KeyboardPushed(#PB_Key_Down)
playerx - (Sin(playerz) * playermove)
playery - (Cos(playerz) * playermove)
EndIf
If KeyboardReleased(#PB_Key_PageUp)
playerfov + 5
ElseIf KeyboardPushed(#PB_Key_PageDown)
playerfov - 5
EndIf
screenDC=StartDrawing(ScreenOutput())
time=ElapsedMilliseconds()
render()
Debug ElapsedMilliseconds()-time
DrawText("ANGLE:" + Str(playerz/(#PI/180)) + "-FPS:" + Str(EP_FPS()))
StopDrawing()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or event=#PB_Event_CloseWindow
Verfasst: 02.12.2005 23:26
von Kaeru Gaman
nur nebenbei....
das AND funktioniert auch bei negativen werten anstandslos...

Verfasst: 02.12.2005 23:35
von Kekskiller
?
Also wenn ich das jetzt richtig verstanden habe, sollte hierbei theoretisch ein Winkel rauskommen und keine 0... Denn ich hab ja mein Array mit den 1024 Feldern, hab atosin auf 512 umgestellt und verwende dafür "anstandslo" -wie du behauptest- eine negative Zahl...
Code: Alles auswählen
#PI = 3.141592
Procedure.f atosin(angle.w)
s.f = (#PI / 512) * angle
ProcedureReturn s
EndProcedure
Dim s(1024)
Dim c(1024)
For z=0 To 512
s(z)=Sin(atosin(z))
c(z)=Cos(atosin(z))
Next
Debug s(-475 & 1024)
Tut mir leid, aber daraus werde ich jetzt pberhaupt nicht schlau... Zumal doch & sowieso theoretisch nur 0 oder 1 ausgibt.
Verfasst: 02.12.2005 23:40
von Kaeru Gaman
äh... nich & 1024... das bit is uninteressant...
&1023 um die unteren bits anzusprechen
damit erhältst du praktisch Winkel modulo 1024... nur viel viel schneller
dein array richtest du von 0 bis 1023 ein
0 = 0° ( 1024 wäre 360° )
256 = 90°
512 = 180°
768 = 270°
usw.usf.
das stimmt bei dir ja so... das array müsste funzen...
[edit]
äh.. nein... mach mal 0 to 1023
außerdem kannst du den Cos aus dem gleichen array holen wie den Sin
Code: Alles auswählen
x = SinArray(Winkel & 1023)
y = SinArray((Winkel+256) & 1023)
Verfasst: 02.12.2005 23:53
von Kekskiller
Du kannst sagen, was du willst, da kommt trotzdem nur 0 oder 1 raus. Das dürfte dann theoretisch auch nur ein 2-Feld-Array sein. Kann es sein, dass du da einen einfachen Logikfehler drinn hast? Egal, wie du den AND-Operator verwendest, z.b. in deinem Beispiel (Winkel & 1023) kommt auch nur 0 oder 1 raus...
Edit: MODULA ist ja wieder was ganz anderes. Sprich dich aus!
Verfasst: 03.12.2005 00:00
von Kaeru Gaman
nein... bei AND 1023 kommen zahlen von 0 bis 1023 raus.
denn:
1023 = 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 + 256 + 512
also damit prüfe ich die 10 untersten bits auf einmal
also erhalte ich durch Zahl&1023 eben das gleiche wie Zahl%1024
es funktioniert eben nur mit zweierpotenzen
a % 2^x
geht schneller mit
a & (2^x-1)
Verfasst: 03.12.2005 00:13
von Kekskiller
Ach, ich Dähmlack, von wegen alles richtig, ich hab nur vergessen, dem Array Float als Datentyp zu geben... Jaja, ist schon gut, ich seh meinen Fehler ein.
Verfasst: 03.12.2005 00:27
von Kaeru Gaman
argl.. das hab ich grad überlesen...
ich dachte schon, das wär ein cast-problem, weil ja ne schleifenvariable int sein muss...
aber durch deine proc wärs ja gelöst gewesen...
geht btw auch, wenn man die #pi als erstes, und die schleifenvariable als letztes schreibt...
dann wird der ausdruck float-gecastet...