iigs-game-engine/tools/scanline-test.py

105 lines
2.4 KiB
Python

# Playground for working through scanline decomposition algorithm
# 1. Shadow Off
# 2. Draw Playfield (sprite OR overlay) AND NOT solid_overlay
# 3. Draw sprites
sprites = [
{ 'top': 10, 'bottom': 17 },
{ 'top': 14, 'bottom': 29 }
]
overlays = [
{ 'top': 0, 'bottom': 7 }
]
MAX_HEIGHT = 199
# Combine a list on ranges into a minimal list by merging overlapping ranges
def simplify(a):
b = []
if len(a) > 0:
last = a[0]
start = last['top']
for r in a[1:]:
if r['top'] <= last['bottom']:
last = r
continue
b.append([start, last['bottom']])
last = r
start = r['top']
b.append([start, last['bottom']])
return b
# Given two sorted lists, merge them together into a minimal set of ranges. This could
# be done as a list merge and then a combine step, but we want to be more efficient and
# do the merge-and-combine at the same time
def merge(a, b):
if len(a) == 0:
return simplify(b)
if len(b) == 0:
return simplify(a)
c = []
i = j = 0
while i < len(a) and j < len(b):
if a[i]['top'] <= b[j]['top']:
c.append(a[i])
i += 1
else:
c.append(b[j])
j += 1
if i < len(a):
c.extend(a[i:])
if j < len(b):
c.extend(b[j:])
return simplify(c)
# Find the lines that need to be drawn with shadowing off
def get_shadow_off_bg(sprites):
ranges = []
if len(sprites) > 0:
last = sprites[0]
start = last['top']
for sprite in sprites[1:]:
if sprite['top'] <= last['bottom']:
last = sprite
continue
ranges.push([start, last['bottom']])
start = sprite['top']
last = sprite
ranges.append([start, last['bottom']])
return ranges
def complement(ranges):
comp = []
if len(ranges) > 0:
if ranges[0][0] > 0:
comp.append([0, ranges[0][0]])
for i in range(1, len(ranges)):
comp.append([ranges[i-1][1]+1, ranges[i][0]])
last = ranges[len(ranges)-1]
if last[1] < MAX_HEIGHT:
comp.append([last[1]+1, MAX_HEIGHT])
return comp
else:
return [0, MAX_HEIGHT]
r = get_shadow_off_bg(sprites)
print(r)
print(complement(r))
print(merge(sprites, overlays))