Python Forum
Need help on making raycasting faster
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Need help on making raycasting faster
#1
I need help making my raycaster faster as it takes time to render the image after
input. I have tried doing the turtle.tracer(0, 0) thing but it is still slow.
P.S. I don't know how to do python keyboard detection so you have to press enter every time you press a letter.


import turtle
import math

# Instructions:
# You can only type in one letter at a time and return
# w = forward
# A = left
# d = right
# s = backwards
# Do not run into the walls partly because I haven't coded the collision
# detection and also partly because it displays an error right after


screen = turtle.Screen()
screen.bgcolor("Black")
turt = turtle.Turtle()
turt.speed(0)
turt.penup()
plr = turtle.Turtle()
plr.penup()
plr.sety(-30)
plr.setx(-30)
plr.setheading(45)

draw = turtle.Turtle()
draw.penup()
draw.pensize(6)
draw.speed(0)

user = ""

angle = -48
distance = 0

lis = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
lis2 = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
def fwd():
  plr.forward(20)
def bck():
  plr.forward(-20)
def lft():
  plr.right(20)
def rgt():
  plr.left(20)

while True:
  while True:
    user = str(input("use the W A S D keys to move around:"))
    if (user == "w"):
      plr.forward(5)
      break
    if (user == "s"):
      plr.forward(-5)
      break
    if (user == "d"):
      plr.left(15)
      break
    if (user == "a"):
      plr.right(15)
      break
  angle = -48
  for i in range(96):
    turt.tracer(0, 0)
    turt.setx(plr.xcor())
    turt.sety(plr.ycor())
    turt.setheading(plr.heading() + angle)
    distance = 0
    while distance != 200:
      turt.tracer(0, 0)
      lis2[i] = 0
      # bounderies
      if (turt.xcor() > 50):
        turt.setx(50)
        lis2[i] = 1
        break
      if (turt.ycor() < -50):
        turt.sety(-50)
        lis2[i] = 2
        break
      if (turt.ycor() > 50):
        turt.sety(50)
        lis2[i] = 2
        break
      if (turt.xcor() < -50):
        turt.setx(-50)
        lis2[i] = 1
        break
      # block
      if (turt.xcor() > 30 and turt.xcor() < 31.5 and turt.ycor() > -20 and turt.ycor() < 20):
        lis2[i] = 3
        break
      if (turt.xcor() > 37 and turt.xcor() < 38.5 and turt.ycor() > -20 and turt.ycor() < 20):
        lis2[i] = 3
        break
      if (turt.ycor() > 20 and turt.ycor() < 21 and turt.xcor() > 30 and turt.xcor() < 38.5):
        lis2[i] = 4
        break
      if (turt.ycor() < -20 and turt.ycor() > -21 and turt.xcor() > 30 and turt.xcor() < 38.5):
        lis2[i] = 4
        break
      # block 2
      if (turt.xcor() > 10 and turt.xcor() < 11.5 and turt.ycor() > -20 and turt.ycor() < 20):
        lis2[i] = 3
        break
      if (turt.xcor() > 17 and turt.xcor() < 18.5 and turt.ycor() > -20 and turt.ycor() < 20):
        lis2[i] = 3
        break
      if (turt.ycor() > 20 and turt.ycor() < 21 and turt.xcor() > 10 and turt.xcor() < 18.5):
        lis2[i] = 4
        break
      if (turt.ycor() < -20 and turt.ycor() > -21 and turt.xcor() > 10 and turt.xcor() < 18.5):
        lis2[i] = 4
        break
      
      turt.forward(1)
      distance = distance + 1
    lis[i] = distance * math.sin(math.radians(90 - angle))
    angle += 1
  draw.setx(-200)
  draw.clear()
  for i in range(96):
    if (lis2[i] == 2):
      draw.color("Mediumblue")
    elif (lis2[i] == 1):
      draw.color("Blue")
    elif (lis2[i] == 3):
      draw.color("Red")
    elif (lis2[i] == 4):
      draw.color("Crimson")
    draw.sety(200)
    draw.sety(-1500 / lis[i])
    draw.pendown()
    draw.sety(1500 / lis[i])
    draw.setx(draw.xcor() + 5)
    draw.penup()
    draw.color("Black")
  draw.update()
  
Reply
#2
The while loop for distance is a big efficiency sink. Every one of those method calls takes time to call and they're the same methods repeatedly. There are 34 method calls in a loop that iterates up to 200 times so, it's potentially 6,800 method calls. It would be faster to call those methods once, store the value in a variable, and then do the logic test; this would equate to 400 methods calls maximum.

Plus, the structure of that if statement should be if...elif...else instead of using break continually.

while distance != 200:
    turt.tracer(0, 0)
    lis2[i] = 0
    # bounderies
    x = turt.xcor()
    y = turt.ycor()

    if x > 50:
        turt.setx(50)
        lis2[i] = 1
    elif y < -50:
        turt.sety(-50)
        lis2[i] = 2
    elif y > 50:
        turt.sety(50)
        lis2[i] = 2
    elif x < -50:
        turt.setx(-50)
        lis2[i] = 1
    # block
    elif 30 < x < 31.5 and -20 < y < 20:
        lis2[i] = 3
    elif 37 < x < 38.5 and -20 < y < 20:
        lis2[i] = 3
    elif 20 < x < 21 and 30 < y < 38.5:
        lis2[i] = 4
    elif -21 < x < -20 and 30 < y < 38.5:
        lis2[i] = 4
    # block 2
    elif 10 < x < 11.5 and -20 < y < 20):
        lis2[i] = 3
    elif 17 < x < 18.5 and -20 < y < 20:
        lis2[i] = 3
    elif 20 < x < 21 and 10 < y  < 18.5:
        lis2[i] = 4
    elif -21 < x < -21 and 10 < y < 18.5:
        lis2[i] = 4

    if lis2[i] != 0:
       break

    turt.forward(1)
    distance += 1
The coloring loop at the end can be simplified with a small dictionary too.

colors = {1: "Blue", 2: "Mediumblue", 3: "Red", 4: "Crimson"}
        
for i in range(96):
    draw.color(colors.get(lis2[i]))
Reply
#3
ok thank you ill go do that now

Its getting faster! I just need find an alternative to "break" because the loop needs to end immediately if the statement is true. anyway here is the updated code, I changed the whole thing up a bit.
import turtle
import math
import pygame
pygame.init()
pygame.display.set_mode()
events = pygame.event.get()

colors = {1: "Blue", 2: "Mediumblue", 3: "Red", 4: "Crimson"}

# Instructions:
# UP = forward
# LEFT = left
# RIGHT = right
# DOWN = backwards
# Do not run into the walls partly because I haven't coded the collision
# detection and also partly because it displays an error right after


screen = turtle.Screen()
screen.bgcolor("Black")
turtx = 0
turty = 0
plrx = -30
plry = -30
plrA = 45

draw = turtle.Turtle()
draw.penup()
draw.pensize(6)
draw.speed(0)
draw.hideturtle()

angle = -30
distance = 0

lis = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
lis2 = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]

while True:
  for event in pygame.event.get():
    if event.type == pygame.KEYDOWN:
      if event.key == pygame.K_LEFT:
        plrA = plrA - 20
        break
      if event.key == pygame.K_RIGHT:
        plrA = plrA + 20
        break
      if event.key == pygame.K_UP:
        plrx = plrx + (math.cos(math.radians(plrA)) * 10)
        plry = plry + (math.sin(math.radians(plrA)) * 10)
        break
      if event.key == pygame.K_DOWN:
        plrx = plrx - (math.cos(math.radians(plrA)) * 10)
        plry = plry - (math.sin(math.radians(plrA)) * 10)
        break
      
  angle = -30
  for i in range(96):
    turtx = plrx
    turty = plry
    distance = 0
    for m in range(150):
      lis2[i] = 0
      # bounderies
      if (turtx > 50):
        lis2[i] = 1
        break
      if (turty < -50):
        lis2[i] = 2
        break
      if (turty > 50):
        lis2[i] = 2
        break
      if (turtx < -50):
        lis2[i] = 1
        break
      # block
      if (turtx > 30 and turtx < 31.5 and turty > -20 and turty < 20):
        lis2[i] = 3
        break
      if (turtx > 37 and turtx < 38.5 and turty > -20 and turty < 20):
        lis2[i] = 3
        break
      if (turty > 20 and turty < 21 and turtx > 30 and turtx < 38.5):
        lis2[i] = 4
        break
      if (turty < -20 and turty > -21 and turtx > 30 and turtx < 38.5):
        lis2[i] = 4
        break
      # block 2
      if (turtx > 10 and turtx < 11.5 and turty > -20 and turty < 20):
        lis2[i] = 3
        break
      if (turtx > 17 and turtx < 18.5 and turty > -20 and turty < 20):
        lis2[i] = 3
        break
      if (turty > 20 and turty < 21 and turtx > 10 and turtx < 18.5):
        lis2[i] = 4
        break
      if (turty < -20 and turty > -21 and turtx > 10 and turtx < 18.5):
        lis2[i] = 4
        break
      
      turtx = turtx + math.cos(math.radians(plrA + angle))
      turty = turty + math.sin(math.radians(plrA + angle))
      distance = distance + 1
    lis[i] = distance * math.sin(math.radians(90 - angle))
    angle += 0.625
  draw.setx(-200)
  draw.clear()
  for i in range(96):
    draw.tracer(0, 0)
    draw.color(colors.get(lis2[i]))
    draw.sety(200)
    draw.sety(-2000 / lis[i])
    draw.pendown()
    draw.sety(2000 / lis[i])
    draw.penup()
    draw.setx(draw.xcor() + 5)
    draw.color("Black")
  draw.update()
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Raycasting GPS coordinates drybulkfreight 10 4,530 Aug-18-2019, 02:54 PM
Last Post: drybulkfreight

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020