mirror of
https://github.com/dschmenk/LightCycles.git
synced 2024-06-10 03:29:33 +00:00
111 lines
4.1 KiB
Python
Executable File
111 lines
4.1 KiB
Python
Executable File
import pygame, math, sys
|
|
from pygame.locals import *
|
|
|
|
DEG_PER_CIRCLE = 128
|
|
DEG_TO_RAD = math.pi*2/DEG_PER_CIRCLE
|
|
FOV = DEG_PER_CIRCLE/3 # FOV in degrees
|
|
PROJDIST = 0.5 #1.5 # Distance to projection plane
|
|
PROJHEIGHT = 2.0 # Height of projection screen
|
|
PROJBOT = 1.5 # Bottom of projection screen
|
|
PROJTOP = PROJBOT+PROJHEIGHT # Top of projection screen
|
|
EYEHEIGHT = PROJBOT+PROJHEIGHT/2 # Eye height
|
|
HORIZON = 16#200
|
|
|
|
tex1 = [[(0,0,0),(255,0,0)],[(0,255,0),(0,0,255)]]
|
|
s = [[0 for x in xrange(DEG_PER_CIRCLE)] for y in xrange(255)]
|
|
t = [[0 for x in xrange(DEG_PER_CIRCLE)] for y in xrange(255)]
|
|
ds = [[0 for x in xrange(DEG_PER_CIRCLE)] for y in xrange(255)]
|
|
dt = [[0 for x in xrange(DEG_PER_CIRCLE)] for y in xrange(255)]
|
|
|
|
def setup(width, height):
|
|
global HORIZON
|
|
global s, t, ds, dt
|
|
|
|
print 'ST_TBL ; S, T, DS, DT angle+scanline table'
|
|
pixfov = math.tan(FOV/2*DEG_TO_RAD) / width/2
|
|
for angle in xrange(DEG_PER_CIRCLE):
|
|
viewv = math.sin(angle*DEG_TO_RAD)
|
|
viewu = math.cos(angle*DEG_TO_RAD)
|
|
scanv = viewu # sin((dirview+90)*DEG_TO_RAD)
|
|
scanu = -viewv # cos((dirview+90)*DEG_TO_RAD)
|
|
for scanline in xrange(0, height):
|
|
if scanline >= HORIZON:
|
|
break
|
|
scanheight = scanline * PROJHEIGHT / height + PROJBOT
|
|
if scanheight >= EYEHEIGHT:
|
|
break
|
|
scandist = EYEHEIGHT * PROJDIST / (EYEHEIGHT - scanheight)
|
|
if scandist > PROJDIST and scandist < 256:
|
|
s[scanline][angle] = viewu * scandist
|
|
t[scanline][angle] = viewv * scandist
|
|
dp = pixfov * scandist
|
|
ds[scanline][angle] = scanu * dp
|
|
dt[scanline][angle] = scanv * dp
|
|
fxs = int(math.floor(s[scanline][angle]*1024+0.5))
|
|
fxt = int(math.floor(t[scanline][angle]*1024+0.5))
|
|
fxds = int(math.floor(ds[scanline][angle]*65536+0.5))
|
|
fxdt = int(math.floor(dt[scanline][angle]*65536+0.5))
|
|
# fxs = int(s[scanline][angle]*1024+0.5) # 6.10 fixpt
|
|
# fxt = int(t[scanline][angle]*1024+0.5) # 6.10 fixpt
|
|
# fxds = int(ds[scanline][angle]*65536+0.5) # 0.16 fixpt
|
|
# fxdt = int(dt[scanline][angle]*65536+0.5) # 0.16 fixpt
|
|
if fxs < 0:
|
|
fxs += 65536
|
|
if fxt < 0:
|
|
fxt += 65536
|
|
if fxds < 0:
|
|
fxds += 65536
|
|
if fxdt < 0:
|
|
fxdt += 65536
|
|
print '\t!WORD\t$%04X, $%04X, $%04X, $%04X\t;scan %d angle %d' % (fxs, fxt, fxds, fxdt, scanline, angle)
|
|
if scanline > HORIZON:
|
|
HORIZON = scanline
|
|
|
|
def texel(s, t):
|
|
return tex1[int(math.floor(s))&1][int(math.floor(t))&1]
|
|
|
|
def draw(pixbuf, width, height, frame):
|
|
xview = 0
|
|
yview = 0
|
|
dirview = frame%DEG_PER_CIRCLE
|
|
for scanline in xrange(HORIZON):
|
|
_s = xview + s[scanline][dirview]
|
|
_t = yview + t[scanline][dirview]
|
|
#
|
|
# Draw right half of scanline
|
|
#
|
|
_ds = ds[scanline][dirview]
|
|
_dt = dt[scanline][dirview]
|
|
scans = _s + _ds / 2
|
|
scant = _t + _dt / 2
|
|
for x in xrange(width/2, width):
|
|
pixbuf[x][(height-1)-scanline] = texel(scans, scant)
|
|
scans += _ds
|
|
scant += _dt
|
|
#
|
|
# Draw left half of scanline
|
|
#
|
|
scans = _s - _ds / 2
|
|
scant = _t - _dt / 2
|
|
for x in xrange(width/2-1, -1, -1):
|
|
pixbuf[x][(height-1)-scanline] = texel(scans, scant)
|
|
scans -= _ds
|
|
scant -= _dt
|
|
|
|
WIDTH = 30#320
|
|
HEIGHT = 40#200
|
|
pygame.init()
|
|
surface = pygame.display.set_mode((WIDTH,HEIGHT))
|
|
surfpix = pygame.PixelArray(surface)
|
|
frame = 0
|
|
setup(WIDTH, HEIGHT)
|
|
while True:
|
|
draw(surfpix, WIDTH, HEIGHT, frame)
|
|
pygame.display.update()
|
|
frame += 1
|
|
for event in pygame.event.get():
|
|
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
|
|
pygame.quit()
|
|
sys.exit()
|
|
|