Advertisement
billysback

Pygame raycaster

Jan 26th, 2014
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.63 KB | None | 0 0
  1. import sys, pygame, math, random
  2. from pygame.locals import *
  3. pygame.init()
  4.  
  5. width, height = 1080, 680
  6. screen = pygame.display.set_mode((width, height))
  7. pygame.display.toggle_fullscreen()
  8. #screen.toggle_fullscreen()
  9.  
  10. teles = []
  11. hitMap = []
  12. for x in range(width):
  13.     hitTab = []
  14.     for y in range(height):
  15.         hitTab.append([1, [255, 255, 255]])
  16.     hitMap.append(hitTab)
  17.  
  18. def drawLine(x1, y1, x2, y2):
  19.     points = []
  20.     if (x2-x1) > 0:
  21.         grad = (y2-y1)/(x2-x1)
  22.         c = y1 - (x1*grad)
  23.         for x in range(min(x1, x2), max(x1, x2)):
  24.             y = math.floor((x*grad) + c)
  25.             points.append([x, y])
  26.         for y in range(min(y1, y2), max(y1, y2)):
  27.             x = math.floor((y/grad) - (c/grad))
  28.             points.append([x, y])
  29.     else:
  30.         for y in range(min(y1, y2), max(y1, y2)):
  31.             points.append([x1, y])
  32.     return points
  33.  
  34. pi = math.pi
  35. def getXY(x, y, a, h):
  36.     ra = a
  37.     if a < pi/2:
  38.         ra = a
  39.     elif a < pi:
  40.         ra = pi-a
  41.     elif a < pi + (pi/2):
  42.         ra = a-pi
  43.     elif a < 2*pi:
  44.         ra = (2*pi)-a
  45.     nx = (math.sin(ra)*h)
  46.     ny = (math.sqrt( (h*h) - (nx*nx) ) )
  47.     if a < pi/2:
  48.         #print("GOT < 90 (pi/2)")
  49.         return [math.floor(x + nx), math.floor(y + ny)]
  50.     elif a < pi:
  51.         #print("GOT < 180 (pi)")
  52.         return [math.floor(x + nx), math.floor(y - ny)]
  53.     elif a < pi + (pi/2):
  54.         #print("GOT < 270 (pi + pi/2)")
  55.         return [math.floor(x - nx), math.floor(y - ny)]
  56.     elif a < 2*pi:
  57.         #print("GOT < 360 (2pi)")
  58.         return [math.floor(x - nx), math.floor(y + ny)]
  59.     elif a == 0 or 2*pi:
  60.         return [math.floor(x), math.floor(y + ny)]
  61.     elif a == pi/2:
  62.         return [math.floor(x + nx), math.floor(y)]
  63.     elif a == pi:
  64.         return [math.floor(x), math.floor(y - ny)]
  65.     elif a == pi + (pi/2):
  66.         return [math.floor(x - nx), math.floor(y)]
  67.     else:
  68.         return [x, y]
  69.  
  70. def castRay2(x, y, a, fov):
  71.     ray = []
  72.     if a == math.radians(0) or a == math.radians(180) or a == math.radians(360):
  73.         step = 1
  74.         if a == math.radians(180):
  75.             step = -1
  76.         typ = 0
  77.         for ye in range(fov):
  78.             cy = y + (ye*step)
  79.             if cy >= 0 and cy < height:
  80.                 if hitMap[x][cy][0] != 1:
  81.                     if hitMap[x][cy][0] == 2:
  82.                         typ = 2
  83.                     ray.append([x, cy, typ, hitMap[x][cy][1]])
  84.                     if hitMap[x][cy][0] == 2:
  85.                         typ = 3
  86.                 else:
  87.                     ray.append([x, cy, 1, hitMap[x][cy][1]])
  88.                     break
  89.             else:
  90.                 break
  91.     elif a == math.radians(90) or a == math.radians(270):
  92.         step = 1
  93.         if a == math.radians(270):
  94.             step = -1
  95.         typ = 0
  96.         for xe in range(fov):
  97.             cx = x + (xe*step)
  98.             if cx >= 0 and cx < width:
  99.                 if hitMap[cx][y][0] != 1:
  100.                     if hitMap[cx][y][0] == 2:
  101.                         typ = 2
  102.                     ray.append([cx, y, typ, hitMap[cx][y][1]])
  103.                     if hitMap[cx][y][0] == 2:
  104.                         typ = 3
  105.                 else:
  106.                     ray.append([cx, y, typ, hitMap[cx][y][1]])
  107.                     break
  108.             else:
  109.                 break
  110.     else:
  111.         typ = 0
  112.         for i in range(fov):
  113.             pos = getXY(x, y, a, i)
  114.             if pos[0] >= 0 and pos[0] < width and pos[1] >= 0 and pos[1] < height:
  115.                 if hitMap[pos[0]][pos[1]][0] != 1:
  116.                     if hitMap[pos[0]][pos[1]][0] == 2:
  117.                         typ = 2
  118.                     ray.append([pos[0], pos[1], typ, hitMap[pos[0]][pos[1]][1]])
  119.                     if hitMap[pos[0]][pos[1]][0] == 2:
  120.                         typ = 3
  121.                 else:
  122.                     ray.append([pos[0], pos[1], typ, hitMap[pos[0]][pos[1]][1]])
  123.                     break
  124.     return ray
  125.  
  126. def getAngle(x1, y1, x2, y2):
  127.     distx = max(x1, x2) - min(x1, x2)
  128.     disty = max(y1, y2) - min(y1, y2)
  129.     dist = math.sqrt( (distx*distx) + (disty*disty) )
  130.     a = math.degrees(math.asin( distx/dist ))
  131.     if x2 > x1 and y2 > y1:
  132.         return a+1
  133.     elif x2 > x1 and y2 < y1:
  134.         return 180 - a
  135.     elif x2 < x1 and y2 < y1:
  136.         return 180 + a
  137.     elif x2 < x1 and y2 > y1:
  138.         return 360 - a
  139.     return a
  140.  
  141. def setCluster(x, y, t):
  142.     for xa in range(-1, 1):
  143.         for ya in range(-1, 1):
  144.             if (x+xa) >= 0 and (x+xa) < width and (y+ya) >= 0 and (y+ya) < height:
  145.                 hitMap[x+xa][y+ya][0] = t
  146.  
  147. def addLine(x1, y1, x2, y2):
  148.     points = drawLine(x1, y1, x2, y2)
  149.     for i in range(len(points)):
  150.         x, y = points[i][0], points[i][1]
  151.         setCluster(x, y, 1)
  152.  
  153. def clearLine(x1, y1, x2, y2):
  154.     points = drawLine(x1, y1, x2, y2)
  155.     for i in range(len(points)):
  156.         x, y = points[i][0], points[i][1]
  157.         setCluster(x, y, 0)
  158.  
  159. def drawHitMap(hmap):
  160.     for x in range(len(hmap)):
  161.         htab = hmap[x]
  162.         for y in range(len(htab)):
  163.             typ = htab[y][0]
  164.             if typ == 1:
  165.                 screen.set_at((x, y), htab[y][1])
  166.             elif typ == 2:
  167.                 screen.set_at((x, y), [255, 0, 0])
  168.  
  169. def drawRay(ray, fov):
  170.     for i in range(len(ray)):
  171.         p = ray[i]
  172.         if p[2] != 1:
  173.             per = (i/fov)*100
  174.             red = math.floor((255/100)*(100-per))
  175.             if p[2] == 2:
  176.                 screen.set_at((p[0], p[1]), [int(red/3), 0, 0])
  177.             elif p[2] == 0:
  178.                 screen.set_at((p[0], p[1]), [red, red, red])
  179.             elif p[2] == 3:
  180.                 screen.set_at((p[0], p[1]), [int(red), 0, 0])
  181.  
  182. def drawWolf(x, y, angle, fov, sight):
  183.     app = (fov/width)
  184.     for cx in range(0, width+1):
  185.         curx = (x*math.cos(x-(width/2)))
  186.         a = ((cx*app) + angle)
  187.         if a > 360:
  188.             a = a - 360
  189.         ray = castRay2(x, y, math.radians(a), sight)
  190.         lowerY = 0
  191.         upperY = 0
  192.         if len(ray) > 0:
  193.             pos = ray[len(ray)-1]
  194.             pos[0] = pos[0]
  195.             dist = math.sqrt( ((pos[0]-x)**2) + ((pos[1]-y)**2) )
  196.             per = 101-((dist/sight)*100)
  197.             h = (height/100)*per
  198.             rh = int(h/2)
  199.             midy = math.floor(height/2)
  200.             lowerY = midy-rh
  201.             upperY = midy+rh
  202.             #print(height, " = height; ", midy, " = midY; ", rh, " = diff H; ", lowerY, " = lowerY; ", upperY, " = upperY")
  203.             #print(pos[3])
  204.         for cy in range(0, height+1):
  205.             if cy < lowerY or (pos[2] == 1 and cy <= midy):
  206.                 screen.set_at((cx, cy), [100, 100, 100])
  207.             elif cy >= lowerY and cy <= upperY and pos[2] != 1:
  208.                 screen.set_at((cx, cy), pos[3])
  209.             elif cy > upperY or pos[2] == 1:
  210.                 screen.set_at((cx, cy), [200, 200, 200])
  211.  
  212. def addRandLine():
  213.     addLine(random.randint(1, width), random.randint(1, height), random.randint(1, width), random.randint(1, height))
  214.  
  215. def addRandSquare():
  216.     pos = [random.randint(1, width), random.randint(1, height)]
  217.     w = random.randint(40, 100)
  218.     h = random.randint(40, 100)
  219.     addLine(pos[0], pos[1], pos[0]+w, pos[1])
  220.     addLine(pos[0]+w, pos[1], pos[0]+w, pos[1]+h)
  221.     addLine(pos[0], pos[1]+h, pos[0]+w, pos[1]+h)
  222.     addLine(pos[0], pos[1]+h, pos[0], pos[1])
  223.     dW = 5
  224.     possible = [
  225.             [pos[0] + int(w/2) - dW, pos[1], pos[0] + int(w/2) + dW, pos[1]],
  226.             [pos[0] + int(w/2) - dW, pos[1] + int(h), pos[0] + int(w/2) + dW, pos[1] + int(h)],
  227.             [pos[0] + int(w), pos[1] + int(h/2) - dW, pos[0] + int(w), pos[1] + int(h/2) + dW],
  228.             [pos[0], pos[1] + int(h/2) - dW, pos[0], pos[1] + int(h/2) + dW]
  229.         ]
  230.     if random.randint(1, 100) <= 60:
  231.         dpos = possible[random.randint(0, len(possible)-1)]
  232.         clearLine(dpos[0], dpos[1], dpos[2], dpos[3])
  233.  
  234. def genDungeon(cell, length):
  235.     gw = math.floor(width/cell) - 2
  236.     gh = math.floor(height/cell) - 2
  237.     grid = []
  238.     for x in range(gw):
  239.         gridTab = []
  240.         for y in range(gh):
  241.             gridTab.append([1, [random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)]])
  242.         grid.append(gridTab)
  243.     cur = [random.randint(0, len(grid)-1), random.randint(0, len(grid[0])-1)]
  244.     startPos = [(cur[0]*cell)  + cell + int(cell/2), (cur[1]*cell) + cell + int(cell/2), 45]
  245.     tele = False
  246.     for i in range(length):
  247.         if tele == False:
  248.             grid[cur[0]][cur[1]][0] = 0
  249.         else:
  250.             grid[cur[0]][cur[1]][0] = 2
  251.             teles.append([(cur[0]*cell)  + cell + int(cell/2), (cur[1]*cell) + cell + int(cell/2)])
  252.             tele = False
  253.         ncur = [cur[0], cur[1]]
  254.         nStop = 0
  255.         while (ncur[0] == cur[0] and ncur[1] == cur[1]) or (ncur[0] < 0 or ncur[0] >= gw or ncur[1] < 0 or ncur[1] >= gh) or (grid[ncur[0]][ncur[1]][0]) == 0 or (grid[ncur[0]][ncur[1]][0]) == 2:
  256.             tpos = random.randint(0, 1)
  257.             dirTy = [-1, 1]
  258.             ncur[tpos] = cur[tpos] + dirTy[random.randint(0, 1)]
  259.             nStop = nStop + 1
  260.             if nStop > 25:
  261.                 break
  262.         if nStop > 25:
  263.             ncur = [cur[0], cur[1]]
  264.             grid[cur[0]][cur[1]][0] = 2
  265.             teles.append([(cur[0]*cell)  + cell + int(cell/2), (cur[1]*cell) + cell + int(cell/2)])
  266.             tele = True
  267.             while grid[ncur[0]][ncur[1]][0] == 0 or grid[ncur[0]][ncur[1]][0] == 2:
  268.                 ncur = [random.randint(0, len(grid)-1), random.randint(0, len(grid[0])-1)]
  269.         cur = ncur
  270.    
  271.     for gx in range(len(grid)):
  272.         tab = grid[gx]
  273.         for gy in range(len(tab)):
  274.             typ = tab[gy][0]
  275.             #print(typ)
  276.             #if typ == 0:
  277.             startX = gx*cell + cell
  278.             startY = gy*cell + cell
  279.             endX = startX + cell
  280.             endY = startY + cell
  281.             midX = int((startX+endX)/2)
  282.             midY = int((startY+endY)/2)
  283.             gapSize = cell/6
  284.             for x in range(startX, endX):
  285.                 for y in range(startY, endY):
  286.                     if typ == 2:
  287.                         if x < (midX-gapSize) or y < midY - gapSize or x > midX + gapSize or y > midY + gapSize:
  288.                             hitMap[x][y][0] = 0
  289.                         else:
  290.                             hitMap[x][y][0] = 2
  291.                     else:
  292.                         hitMap[x][y][0] = typ
  293.                         if typ == 1:
  294.                             hitMap[x][y][1] = tab[gy][1]
  295.     return startPos
  296.  
  297. stepper = 1
  298. sight = 90
  299. fov = 70
  300. def drawGame(pos, af, wolf):
  301.     screen.fill([0, 0, 0])
  302.     #drawHitMap(hitMap)
  303.     #print(af)
  304.     change = (fov*stepper)
  305.     #if fov + af > 360:
  306.     #    for a in range(int(360-af), int(360-af+fov)):
  307.     #        ra = a
  308.     #        if ra < 0:
  309.     #            ra =
  310.     #        drawRay(castRay2(pos[0], pos[1], math.radians(a), sight), sight)
  311.     #else:
  312.     if wolf:
  313.         drawWolf(player[0], player[1], player[2], fov, sight)
  314.     else:
  315.         #drawHitMap(hitMap)
  316.         for a in range(0, int(fov*stepper), 1):
  317.             ra = int( (a/stepper) + af )
  318.             if ra < 0:
  319.                 ra = 360 + ra
  320.             if ra >= 360:
  321.                 ra = (ra - 360)
  322.             drawRay(castRay2(pos[0], pos[1], math.radians(ra), sight), sight)
  323.         screen.set_at((player[0], player[1]), [0, 0, 255])
  324.     pygame.display.flip()
  325.  
  326.  
  327. isWolf = False
  328. player = genDungeon(15, 500)
  329. drawGame(player, player[2], isWolf)
  330.  
  331. speed = 2
  332. slow = 25
  333. turnSpeed = 5
  334.  
  335. ltick = pygame.time.get_ticks()
  336. teled = False
  337. while 1:
  338.     for event in pygame.event.get():
  339.         if event.type == QUIT:
  340.             sys.exit()
  341.  
  342.     if pygame.time.get_ticks() - ltick > slow:
  343.         ltick = pygame.time.get_ticks()
  344.  
  345.         prsd = pygame.key.get_pressed()
  346.         mpr = pygame.mouse.get_pressed()
  347.         mx, my = pygame.mouse.get_pos()
  348.         lpos = [player[0], player[1], player[2]]
  349.         if prsd[pygame.K_UP] or prsd[pygame.K_w]:
  350.             if isWolf == False:
  351.                 player[1] = player[1] - speed
  352.             else:
  353.                 npos = getXY(player[0], player[1], math.radians(player[2] + (fov/2)), speed)
  354.                 player = [npos[0], npos[1], player[2]]
  355.         if prsd[pygame.K_LEFT] or prsd[pygame.K_a]:
  356.             if isWolf == False:
  357.                 player[0] = player[0] - speed
  358.             else:
  359.                 npos = getXY(player[0], player[1], math.radians(player[2] + (fov/2) + 270), speed)
  360.                 player = [npos[0], npos[1], player[2]]
  361.         if prsd[pygame.K_DOWN] or prsd[pygame.K_s]:
  362.             if isWolf == False:
  363.                 player[1] = player[1] + speed
  364.             else:
  365.                 npos = getXY(player[0], player[1], math.radians(player[2] + (fov/2) + 180), speed)
  366.                 player = [npos[0], npos[1], player[2]]
  367.         if prsd[pygame.K_RIGHT] or prsd[pygame.K_d]:
  368.             if isWolf == False:
  369.                 player[0] = player[0] + speed
  370.             else:
  371.                 npos = getXY(player[0], player[1], math.radians(player[2] + (fov/2) + 90), speed)
  372.                 player = [npos[0], npos[1], player[2]]
  373.         if mpr[0] or mpr[1]:
  374.             npos = getXY(player[0], player[1], math.radians(player[2] + (fov/2)), speed)
  375.             player = [npos[0], npos[1], player[2]]
  376.         if prsd[pygame.K_q]:
  377.             player[2] = player[2] - turnSpeed
  378.             if player[2] < 0:
  379.                 player[2] = 360 + player[2]
  380.         if prsd[pygame.K_e]:
  381.             player[2] = player[2] + turnSpeed
  382.             if player[2] > 360:
  383.                 player[2] = 360 - player[2]
  384.         if prsd[pygame.K_r]:
  385.             isWolf = (isWolf == False)
  386.             drawGame(player, player[2], isWolf)
  387.         if isWolf == False:
  388.             player[2] = int(getAngle(player[0], player[1], mx, my)) - (fov/2)
  389.         if player[2] < 0:
  390.             player[2] = 360 + player[2]
  391.         if player[2] > 360:
  392.             player[2] = player[2] - 360
  393.         if lpos[0] != player[0] or lpos[1] != player[1] or lpos[2] != player[2]:
  394.             if player[0] < 0 or player[0] >= width or player[1] < 0 or player[1] >= height or hitMap[player[0]][player[1]][0] == 1:
  395.                 player = lpos
  396.             if hitMap[player[0]][player[1]][0] == 2 and teled == False:
  397.                 telepos = teles[random.randint(0, len(teles)-1)]
  398.                 player = [telepos[0], telepos[1], player[2]]
  399.                 teled = True
  400.             elif hitMap[player[0]][player[1]][0] != 2 and teled == True:
  401.                 teled = False
  402.             drawGame(player, player[2], isWolf)
  403.             #print(player[2], "degrees, (", mx, ",", my, "), (", player[0], ",", player[1], ")")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement