Skip to content

Commit

Permalink
refactored math calculations to numba pre-compiled functions
Browse files Browse the repository at this point in the history
  • Loading branch information
ryancollingwood committed Oct 12, 2018
1 parent 51ac2a2 commit dd84917
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 37 deletions.
13 changes: 7 additions & 6 deletions GENERATION.py
Expand Up @@ -6,6 +6,7 @@
import SETTINGS
import TEXTURES
import LEVELS
from GEOM import cos_radians, sin_radians

class Generator:

Expand Down Expand Up @@ -264,8 +265,8 @@ def rotate_segment(self, segment):
tempx = item[0][0] - origin[0]
tempy = item[0][1] - origin[1]

tempx1 = math.cos(math.radians(90)) * tempx - math.sin(math.radians(90)) * tempy
tempy1 = math.sin(math.radians(90)) * tempx + math.cos(math.radians(90)) * tempy
tempx1 = cos_radians(90) * tempx - sin_radians(90) * tempy
tempy1 = sin_radians(90) * tempx + cos_radians(90) * tempy

tempx1 += origin[0]
tempy1 += origin[1]
Expand All @@ -280,8 +281,8 @@ def rotate_segment(self, segment):
tempx = npc[0][0] - origin[0]
tempy = npc[0][1] - origin[1]

tempx1 = math.cos(math.radians(90)) * tempx - math.sin(math.radians(90)) * tempy
tempy1 = math.sin(math.radians(90)) * tempx + math.cos(math.radians(90)) * tempy
tempx1 = cos_radians(90) * tempx - sin_radians(90) * tempy
tempy1 = sin_radians(90) * tempx + cos_radians(90) * tempy

tempx1 += origin[0]
tempy1 += origin[1]
Expand All @@ -298,8 +299,8 @@ def rotate_segment(self, segment):
tempx = rotseg.player_pos[0] - origin[0]
tempy = rotseg.player_pos[1] - origin[1]

tempx1 = math.cos(math.radians(90)) * tempx - math.sin(math.radians(90)) * tempy
tempy1 = math.sin(math.radians(90)) * tempx + math.cos(math.radians(90)) * tempy
tempx1 = cos_radians(90) * tempx - sin_radians(90) * tempy
tempy1 = sin_radians(90) * tempx + cos_radians(90) * tempy

tempx1 += origin[0]
tempy1 += origin[1]
Expand Down
30 changes: 29 additions & 1 deletion GEOM.py
Expand Up @@ -29,6 +29,7 @@ def sort_atan(x):
if x.type == 'end':
SETTINGS.end_angle = theta

# if a consumer requires abs they can abs
#theta = abs(theta)

return theta
Expand Down Expand Up @@ -81,6 +82,33 @@ def get_camera_plane_for_angle(angle, player_rect_center, tile_size):
return H_x, H_y, V_x, V_y, angle, cos_radians_angle, tan_radians_angle


@jit(nopython=True)
def cos_radians(angle):
return math.cos(math.radians(angle))


@jit(nopython=True)
def tan_radians(angle):
return math.tan(math.radians(angle))


@jit(nopython=True)
def sin_radians(angle):
return math.sin(math.radians(angle))


@jit(nopython=True)
def straight_line_distance(xpos, ypos):
return math.sqrt(xpos * xpos + ypos * ypos)
return math.sqrt(xpos * xpos + ypos * ypos)

x = point.map_pos[0] + point.map_pos[1]
y = end.map_pos[0] + end.map_pos[1]
h = abs(x - y)
return h


@jit(nopython=True)
def max_grid_distance(map_pos_a, map_pos_b):
x = map_pos_a[0] + map_pos_a[1]
y = map_pos_b[0] + map_pos_b[1]
return abs(x - y)
19 changes: 10 additions & 9 deletions MAIN.py
Expand Up @@ -231,16 +231,17 @@ def render_screen(canvas):
SETTINGS.zbuffer = sorted(SETTINGS.zbuffer, key=sort_distance, reverse=True)
SETTINGS.all_solid_tiles = sorted(SETTINGS.all_solid_tiles, key=lambda x: (x.type, x.atan, x.distance))


#Calculate which tiles are visible
for tile in SETTINGS.all_solid_tiles:
if tile.distance and SETTINGS.tile_visible[tile.ID]:
if abs(tile.atan) <= SETTINGS.fov:
if tile.distance < SETTINGS.render * SETTINGS.tile_size:
SETTINGS.rendered_tiles.append(tile)

elif tile.distance <= SETTINGS.tile_size * 1.5:
SETTINGS.rendered_tiles.append(tile)
SETTINGS.rendered_tiles = [
tile for tile in SETTINGS.all_solid_tiles if
tile.distance and SETTINGS.tile_visible[tile.ID] and
(
(abs(tile.atan) <= SETTINGS.fov and
tile.distance < SETTINGS.render * SETTINGS.tile_size)
or
(tile.distance <= SETTINGS.tile_size * 1.5)
)
]

#Render all items in zbuffer
for item in SETTINGS.zbuffer:
Expand Down
3 changes: 2 additions & 1 deletion MAP.py
Expand Up @@ -7,6 +7,7 @@
import math
import random
import os
from GEOM import straight_line_distance

class Map:
'''== Create the map ==\narray -> Level to be loaded'''
Expand Down Expand Up @@ -125,7 +126,7 @@ def draw(self, canvas):
def get_dist(self, pos, *called):
xpos = self.rect.center[0] - pos[0]
ypos = pos[1] - self.rect.center[1]
self.distance = math.sqrt(xpos*xpos + ypos*ypos)
self.distance = straight_line_distance(xpos, ypos)

if (self.state and self.state != 'closed') and called != ('npc',): #lol
self.sesam_luk_dig_op()
Expand Down
7 changes: 4 additions & 3 deletions NPC.py
Expand Up @@ -7,6 +7,7 @@
import random
import math
import pygame
from GEOM import straight_line_distance, cos_radians, sin_radians
#stats format in bottom of script
#pos is in tiles, face in degrees, frame_interval is seconds between frames, speed is pixels/second

Expand Down Expand Up @@ -230,7 +231,7 @@ def render(self):
xpos = SETTINGS.player_rect.centerx - self.rect.centerx
ypos = SETTINGS.player_rect.centery - self.rect.centery

self.dist = math.sqrt(xpos*xpos + ypos*ypos)
self.dist = straight_line_distance(xpos, ypos)

if self.dist <= SETTINGS.render * SETTINGS.tile_size:
theta = math.atan2(-ypos, xpos) % (2*math.pi)
Expand Down Expand Up @@ -716,8 +717,8 @@ def animate(self, animation):
self.drop_item()
SETTINGS.statistics['last enemies'] += 1
elif self.knockback > 0:
self.collide_update(-math.cos(math.radians(self.postheta))*self.knockback, 0)
self.collide_update(0, math.sin(math.radians(self.postheta))*self.knockback)
self.collide_update(-cos_radians(self.postheta)*self.knockback, 0)
self.collide_update(0, sin_radians(self.postheta)*self.knockback)
self.knockback = int(self.knockback*0.8)

#hurt animation
Expand Down
14 changes: 4 additions & 10 deletions PATHFINDING.py
@@ -1,5 +1,6 @@
import SETTINGS
import random
from GEOM import max_grid_distance

#There is some whack error handling. This is because this might be used manually by a human and therefore it needs some human-friendly feedback.
#This is the A* pathfinding algorithm for NPC movement and more
Expand Down Expand Up @@ -55,7 +56,7 @@ def pathfind(start, end):

if not error:
#f_value has to be determined after creation of node.
openlist[start_point] = [0, find_distance(start_point, end_point), 0, None]
openlist[start_point] = [0, max_grid_distance(start_point.map_pos, end_point.map_pos), 0, None]
openlist[start_point][2] = f_value(start_point, openlist)
current_point = start_point

Expand Down Expand Up @@ -91,7 +92,7 @@ def pathfind(start, end):

if (adj.type == 'hdoor' or adj.type == 'vdoor' or not SETTINGS.tile_solid[adj.ID]) and adj not in closedlist:
if (adj in openlist and openlist[adj][0] > closedlist[current_point][0]+1) or adj not in openlist:
openlist[adj] = [closedlist[current_point][0]+1, find_distance(adj, end_point), 0, current_point]
openlist[adj] = [closedlist[current_point][0]+1, max_grid_distance(adj.map_pos, end_point.map_pos), 0, current_point]
openlist[adj][2] = f_value(adj, openlist)

try:
Expand Down Expand Up @@ -119,14 +120,7 @@ def find_near_position(position):
return random.choice(chosen_tiles)
else:
return None


def find_distance(point, end):
x = point.map_pos[0] + point.map_pos[1]
y = end.map_pos[0] + end.map_pos[1]
h = abs(x - y)
return h



def f_value(point, openlist):
f = openlist[point][2] = openlist[point][0] + openlist[point][1]
Expand Down
5 changes: 3 additions & 2 deletions PLAYER.py
Expand Up @@ -7,6 +7,7 @@
import pygame
import math
import os
from GEOM import cos_radians, sin_radians

class Player:

Expand Down Expand Up @@ -55,9 +56,9 @@ def __init__(self, pos):

def direction(self, offset, distance):
if distance == 0:
direction = [math.cos(math.radians(self.angle + offset)), -math.sin(math.radians(self.angle + offset))]
direction = [cos_radians(self.angle + offset), -sin_radians(self.angle + offset)]
else:
direction = [(math.cos(math.radians(self.angle + offset))) * distance, (-math.sin(math.radians(self.angle + offset))) * distance]
direction = [cos_radians(self.angle + offset) * distance, (-sin_radians(self.angle + offset)) * distance]
return direction

def control(self, canvas):
Expand Down
7 changes: 4 additions & 3 deletions RAYCAST.py
Expand Up @@ -3,7 +3,7 @@
import pygame
import math

from GEOM import sort_atan, get_camera_plane_for_angle
from GEOM import sort_atan, get_camera_plane_for_angle, tan_radians
import SETTINGS

pygame.init()
Expand Down Expand Up @@ -79,7 +79,7 @@ def __init__(self, canvas, canvas2):
self.wall_height = int(SETTINGS.canvas_target_height / self.res)
self.wall_width_to_height_difference = self.wall_width - self.wall_height
self.fov_mod = self.fov * 0.8
self.wall_height_mod = (360 / math.tan(math.radians(self.fov_mod))) * self.wall_width_to_height_difference
self.wall_height_mod = (360 / tan_radians(self.fov_mod)) * self.wall_width_to_height_difference
self.canvas = canvas
self.canvas2 = canvas2

Expand Down Expand Up @@ -516,9 +516,10 @@ def control(self, end_pos, ray_number, tile_len, player_rect, texture, offset, c

def render_screen(self, ray_number, wall_dist, texture, offset, current_tile, vh, end_pos):
if wall_dist:
# wall_height = int((self.tile_size / wall_dist) * (360 / math.tan(math.radians(SETTINGS.fov * 0.8))))

# wall_height = int((self.tile_size / wall_dist) * (360 / tan_radians(SETTINGS.fov * 0.8)))
wall_height = int((self.tile_size / wall_dist) * self.wall_height_mod)

SETTINGS.zbuffer.append(Slice((texture.slices[offset], 0), texture.texture, texture.rect.width, vh))
SETTINGS.zbuffer[ray_number].distance = wall_dist
rendered_slice = pygame.transform.scale(SETTINGS.zbuffer[ray_number].slice, (self.wall_width, wall_height))
Expand Down
6 changes: 4 additions & 2 deletions SPRITES.py
@@ -1,6 +1,7 @@
import pygame
import math
import SETTINGS
from GEOM import straight_line_distance, tan_radians

# I noticed, that the sprites are not projected correctly. However, I do not have the guts to fix it. Feel free to take a look.

Expand Down Expand Up @@ -42,7 +43,8 @@ def get_pos(self, canvas):
xpos = self.rect.centerx - SETTINGS.player_rect[0]
ypos = SETTINGS.player_rect[1] - self.rect.centery

dist = math.sqrt(xpos*xpos + ypos*ypos)
dist = straight_line_distance(xpos, ypos)

if dist == 0:
dist += 0.0001
self.distance = dist
Expand All @@ -62,7 +64,7 @@ def get_pos(self, canvas):

xTmp = yTmp * SETTINGS.canvas_actual_width / fov

sprite_height = int((self.rect.height / dist) * (100 / math.tan(math.radians(fov * 0.8))))
sprite_height = int((self.rect.height / dist) * (100 / tan_radians(fov * 0.8)))
if sprite_height > 2500:
sprite_height = 2500

Expand Down

0 comments on commit dd84917

Please sign in to comment.