def __init__(self, size): os.environ["SDL_VIDEO_CENTERED"] = "1" pygame.init() self.size = size self.screen = pygame.display.set_mode(self.size) self.surf = pygame.Surface(self.size) self.clock = pygame.time.Clock() self.running = True self.stage = 1 self.ray1 = Raycasting((200, 320), (500, 50)) self.ray2 = Raycasting((200, 320), (200, 50)) self.ray3 = Raycasting((200, 320), (300, 50)) self.make_wall(10)
def look_around(self, pos, dist): ray = Ray(pos, (1,1)) col_sphere = ray.checklength(self.mob.collision.current_quad) if col_sphere < 80: westpoint = (pos[0] - dist, pos[1]) west = self._raycast(pos, westpoint) eastpoint = (pos[0] + dist, pos[1]) east = self._raycast(pos, eastpoint) southpoint = (pos[0], pos[1] + dist) south = self._raycast(pos, southpoint) northpoint = (pos[0], pos[1] - dist) north = self._raycast(pos, northpoint) col_sphere = False return {"west":west, "east":east, "south":south, "north":north} else: return {}
def __init__(self, size): os.environ["SDL_VIDEO_CENTERED"] = "1" pygame.init() self.size = size self.screen = pygame.display.set_mode(self.size) self.surf = pygame.Surface(self.size) self.clock = pygame.time.Clock() self.myfont = pygame.font.SysFont("arial", 20) self.text1 = self.myfont.render("Press 1, 2 or 3 to pick a Ray", True, (0,0,0)) self.text2 = self.myfont.render("Left Mouse Button for point A", True, (0,0,0)) self.text3 = self.myfont.render("Right Mouse Button for point B", True, (0,0,0)) self.txt1_rect = pygame.Rect(50, 10, 20, 20) self.txt2_rect = pygame.Rect(50, 30, 20, 20) self.txt3_rect = pygame.Rect(50, 50, 20, 20) self.running = True self.stage = 1 self.ray1 = Raycasting((200, 320), (500, 50)) self.ray2 = Raycasting((200, 320), (200, 50)) self.ray3 = Raycasting((200, 320), (300, 50)) self.make_wall(10) # Set the Number to any amount of tiles you want in the wall
def __init__(self, level, windowSize, totalRays, fovDegrees, targetFps): self.level = level self.windowSize = windowSize self.fovDegrees = fovDegrees self.targetFps = targetFps self.moveSpeed = NORMALIZED_MOVE * (60 / targetFps) self.turnSpeed = NORMALIZED_TURN * (60 / targetFps) * (totalRays / 600) self.cataclysmSpeed = NORMALIZED_CATACLYSM * 0.00001 * (60 / targetFps) self.raycasting = None self.screen = None self.font = None self.minimap = None self.fovRays = None self.pixelsPerRay = None self.distanceToProjection = None self.player = None self.winScreen = None # Initialize raycasting logic self.raycasting = Raycasting(totalRays, BLOCK_SIZE, self.level) # Initialize pygame pygame.init() pygame.display.set_caption("Raycasting labyrint") self.screen = pygame.display.set_mode(self.windowSize) # Prepare font rendering pygame.font.init() self.font = pygame.font.SysFont("Sans Serif", 30) # Prepare minimap minimapSize = self.level.get_size() * BLOCK_SIZE // MINIMAP_SIZE_DIV self.minimap = pygame.Surface((minimapSize.x, minimapSize.y)) # Compute fov related stuff self.fovRays = self.raycasting.degrees_to_ray_number(self.fovDegrees) self.pixelsPerRay = windowSize[0] // (totalRays // (360 // self.fovDegrees)) # Compute distance between player and the projection plane (also fov stuff) self.distanceToProjection = int( (PROJECTION_WIDTH) / (tan(radians(self.fovDegrees / 2)))) # Prepare fisheye correction self.fisheyeCoefficients = self.raycasting.fisheye_coefficients( self.fovDegrees, self.fovRays) # Create player object startPos = self.level.get_start_block() * BLOCK_SIZE startPos[0] = startPos.x + (BLOCK_SIZE // 2) # Center vertically startPos[1] = startPos.y + (BLOCK_SIZE // 2) # Center horizontally self.player = Player(startPos, 0, self.raycasting, self.fovRays) # Create win screen self.winScreen = pygame.Surface(windowSize, flags=pygame.SRCALPHA) self.winScreen.fill( (CEIL_COLOR[0], CEIL_COLOR[1], CEIL_COLOR[2], WIN_SCREEN_OPACITY)) youWon = self.font.render("You won!", False, TEXT_COLOR) pressQ = self.font.render("Press 'Q' to quit.", False, TEXT_COLOR) self.winScreen.blit(youWon, (8, 8)) self.winScreen.blit(pressQ, (8, 40))
class Game: """ Represents state of the game. Initializes pygame and all necessary variables and constants on object creation. """ def __init__(self, level, windowSize, totalRays, fovDegrees, targetFps): self.level = level self.windowSize = windowSize self.fovDegrees = fovDegrees self.targetFps = targetFps self.moveSpeed = NORMALIZED_MOVE * (60 / targetFps) self.turnSpeed = NORMALIZED_TURN * (60 / targetFps) * (totalRays / 600) self.cataclysmSpeed = NORMALIZED_CATACLYSM * 0.00001 * (60 / targetFps) self.raycasting = None self.screen = None self.font = None self.minimap = None self.fovRays = None self.pixelsPerRay = None self.distanceToProjection = None self.player = None self.winScreen = None # Initialize raycasting logic self.raycasting = Raycasting(totalRays, BLOCK_SIZE, self.level) # Initialize pygame pygame.init() pygame.display.set_caption("Raycasting labyrint") self.screen = pygame.display.set_mode(self.windowSize) # Prepare font rendering pygame.font.init() self.font = pygame.font.SysFont("Sans Serif", 30) # Prepare minimap minimapSize = self.level.get_size() * BLOCK_SIZE // MINIMAP_SIZE_DIV self.minimap = pygame.Surface((minimapSize.x, minimapSize.y)) # Compute fov related stuff self.fovRays = self.raycasting.degrees_to_ray_number(self.fovDegrees) self.pixelsPerRay = windowSize[0] // (totalRays // (360 // self.fovDegrees)) # Compute distance between player and the projection plane (also fov stuff) self.distanceToProjection = int( (PROJECTION_WIDTH) / (tan(radians(self.fovDegrees / 2)))) # Prepare fisheye correction self.fisheyeCoefficients = self.raycasting.fisheye_coefficients( self.fovDegrees, self.fovRays) # Create player object startPos = self.level.get_start_block() * BLOCK_SIZE startPos[0] = startPos.x + (BLOCK_SIZE // 2) # Center vertically startPos[1] = startPos.y + (BLOCK_SIZE // 2) # Center horizontally self.player = Player(startPos, 0, self.raycasting, self.fovRays) # Create win screen self.winScreen = pygame.Surface(windowSize, flags=pygame.SRCALPHA) self.winScreen.fill( (CEIL_COLOR[0], CEIL_COLOR[1], CEIL_COLOR[2], WIN_SCREEN_OPACITY)) youWon = self.font.render("You won!", False, TEXT_COLOR) pressQ = self.font.render("Press 'Q' to quit.", False, TEXT_COLOR) self.winScreen.blit(youWon, (8, 8)) self.winScreen.blit(pressQ, (8, 40)) def run(self): """ Main game loop. """ clock = pygame.time.Clock() keepGoing = True playerHasMoved = False timerOn = False timer = 0.0 win = False # Set to True when player reaches the flag drawMinimap = False cataclysm = 0.0 # Win screen animation time cataclysmedRays = [0] * self.raycasting.get_total_rays() while keepGoing: # # Events and user input # # Handle events for event in pygame.event.get(): if event.type == pygame.QUIT: keepGoing = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: # If 'q' was pressed down # Quit game keepGoing = False if event.key == pygame.K_m: # If 'm' was pressed down # Toggle minimap drawMinimap = not drawMinimap # Player and camera movement pressedKeys = pygame.key.get_pressed() self.moveSpeed *= 1.0 - cataclysm if pressedKeys[pygame.K_w]: self.player.move_forward(self.moveSpeed) if not playerHasMoved: playerHasMoved = True timerOn = True if pressedKeys[pygame.K_s]: self.player.move_backward(self.moveSpeed) if not playerHasMoved: playerHasMoved = True timerOn = True if pressedKeys[pygame.K_a]: self.player.move_left(self.moveSpeed) if not playerHasMoved: playerHasMoved = True timerOn = True if pressedKeys[pygame.K_d]: self.player.move_right(self.moveSpeed) if not playerHasMoved: playerHasMoved = True timerOn = True if pressedKeys[pygame.K_j]: self.player.turn(-self.turnSpeed) if pressedKeys[pygame.K_l]: self.player.turn(self.turnSpeed) # # Win stuff # # Check if flag was reached if (not win) and self.player.get_pos( ) // BLOCK_SIZE == self.level.get_flag_block(): win = True timerOn = False self.moveSpeed /= 2.0 self.turnSpeed //= 2 # Animate cataclysm i = 0 while i < len(cataclysmedRays): if cataclysmedRays[i] < 3: if random() < cataclysm: cataclysmedRays[i] = 1 if random() < cataclysm: cataclysmedRays[i] = 2 if random() < cataclysm: cataclysmedRays[i] = 3 i += 1 if win: if cataclysm < 1.0: cataclysm += self.cataclysmSpeed else: cataclysm = 1.0 # # Rendering # # Draw floor and ceiling self.screen.fill(FLOOR_COLOR) ceilRect = pygame.Rect(0, 0, self.windowSize[0], self.windowSize[1] // 2) pygame.draw.rect(self.screen, CEIL_COLOR, ceilRect) # Render walls distances, intersections, flagDistances = self.raycasting.cast_rays( # Cast rays self.player.get_left_ray(), self.player.get_right_ray(), self.player.get_pos(), messUpRays=cataclysmedRays) for i, distance in enumerate(distances): if not distance is None: # # Draw a column coresponding to each cast ray # currPixel = i * self.pixelsPerRay # Compute height of the column if -1.0 < distance < 1.0: height = self.windowSize[1] else: height = self.windowSize[ 1] / distance * self.distanceToProjection # Apply fisheye correction height *= self.fisheyeCoefficients[i] # Compute color of the column colorCoeficient = distance / RENDER_DISTANCE if colorCoeficient > 1.0: colorCoeficient = 1.0 red = WALL_COLOR[0] * (1.0 - colorCoeficient) + \ CEIL_COLOR[0] * colorCoeficient green = WALL_COLOR[1] * (1.0 - colorCoeficient) + \ CEIL_COLOR[1] * colorCoeficient blue = WALL_COLOR[2] * (1.0 - colorCoeficient) + \ CEIL_COLOR[2] * colorCoeficient color = (red, green, blue) # Draw the column column = pygame.Rect( currPixel, self.windowSize[1] // 2 - (height // 2), self.pixelsPerRay, height) pygame.draw.rect(self.screen, color, column) # Render flag for i, distance in enumerate(flagDistances): if not distance is None: currPixel = i * self.pixelsPerRay # Compute height of the column if -0.1 < distance < 0.1: height = self.windowSize[1] else: height = self.windowSize[ 1] / distance * self.distanceToProjection / FLAG_HEIGHT_DIV # Apply fisheye correction height *= self.fisheyeCoefficients[i] # Compute color of the column colorCoeficient = distance / RENDER_DISTANCE if colorCoeficient > 1.0: colorCoeficient = 1.0 red = FLAG_COLOR[0] * (1.0 - colorCoeficient) + \ CEIL_COLOR[0] * colorCoeficient green = FLAG_COLOR[1] * (1.0 - colorCoeficient) + \ CEIL_COLOR[1] * colorCoeficient blue = FLAG_COLOR[2] * (1.0 - colorCoeficient) + \ CEIL_COLOR[2] * colorCoeficient color = (red, green, blue) # Draw the column column = pygame.Rect( currPixel, self.windowSize[1] // 2 - (height // 2), self.pixelsPerRay, height) pygame.draw.rect(self.screen, color, column) # # Draw UI # # Minimap if drawMinimap: # Draw walls on minimap self.minimap.fill(FLOOR_COLOR) for x, wall_column in enumerate(self.level.get_walls()): for y, wall in enumerate(wall_column): if wall: rectSize = BLOCK_SIZE // MINIMAP_SIZE_DIV rectX = x * rectSize rectY = y * rectSize rect = pygame.Rect(rectX, rectY, rectSize, rectSize) pygame.draw.rect(self.minimap, WALL_COLOR, rect) # Draw flag on minimap x, y = self.level.get_flag_block() rectSize = BLOCK_SIZE // MINIMAP_SIZE_DIV rectX = x * rectSize rectY = y * rectSize rect = pygame.Rect(rectX, rectY, rectSize, rectSize) pygame.draw.rect(self.minimap, FLAG_COLOR, rect) # Draw player on minimap rectX = self.player.get_pos().x // MINIMAP_SIZE_DIV rectY = self.player.get_pos().y // MINIMAP_SIZE_DIV rectX -= MINIMAP_PLAYER_SIZE // 2 rectY -= MINIMAP_PLAYER_SIZE // 2 rect = pygame.Rect(rectX, rectY, MINIMAP_PLAYER_SIZE, MINIMAP_PLAYER_SIZE) pygame.draw.rect(self.minimap, MINIMAP_COLOR, rect) # Draw intersections (of rays that have been cast) on minimap for intersection in intersections: if not intersection is None: rectX = intersection.x // MINIMAP_SIZE_DIV rectY = intersection.y // MINIMAP_SIZE_DIV rect = pygame.Rect(rectX, rectY, 1, 1) pygame.draw.rect(self.minimap, MINIMAP_COLOR, rect) # Blit minimap onto window self.screen.blit(self.minimap, (0, 0)) # Fps fpsCount = ceil(clock.get_fps()) fpsText = "fps: %d" % (fpsCount) color = TEXT_COLOR if fpsCount > (self.targetFps - 10) else MINIMAP_COLOR fpsSurface = self.font.render(fpsText, False, color) self.screen.blit(fpsSurface, (self.windowSize[0] - (7 * 10) - 8, 8)) # Win screen if win: self.screen.blit(self.winScreen, (0, 0)) # Timer timeText = "time: %.2f s" % (timer / 1000) timeSurface = self.font.render(timeText, False, TEXT_COLOR) self.screen.blit(timeSurface, (self.windowSize[0] - (12 * 10) - 8, self.windowSize[1] - 16 - 8)) # # Finish drawing # pygame.display.flip() # # Time # if timerOn: timer += clock.get_time() clock.tick(self.targetFps)
class Main(object): def __init__(self, size): os.environ["SDL_VIDEO_CENTERED"] = "1" pygame.init() self.size = size self.screen = pygame.display.set_mode(self.size) self.surf = pygame.Surface(self.size) self.clock = pygame.time.Clock() self.running = True self.stage = 1 self.ray1 = Raycasting((200, 320), (500, 50)) self.ray2 = Raycasting((200, 320), (200, 50)) self.ray3 = Raycasting((200, 320), (300, 50)) self.make_wall(10) def main_loop(self, fps=0): while self.running: pygame.display.set_caption("Raytest. FPS: %i" % self.clock.get_fps()) self.events() self.update() self.draw() pygame.display.flip() self.clock.tick(fps) def events(self): for event in pygame.event.get(): if event.type == QUIT: self.running = False elif event.type == KEYDOWN: self.key_down(event.key) elif event.type == MOUSEBUTTONDOWN: self.mouse_down(event.button, event.pos) def key_down(self, key): if key == K_1: self.stage = 1 elif key == K_2: self.stage = 2 elif key == K_3: self.stage = 3 def mouse_down(self, button, pos): if self.stage == 1: if button == 1: self.ray2.pos = vec2d(pos) elif button == 3: self.ray2.target = vec2d(pos) elif self.stage == 2: if button == 1: self.ray3.pos = vec2d(pos) elif button == 3: self.ray3.target = vec2d(pos) elif self.stage == 3: if button == 1: self.ray1.pos = vec2d(pos) elif button == 3: self.ray1.target = vec2d(pos) def update(self): self.points = self.ray1.cast(self.wallgroup, 5, True) self.points2 = self.ray3.cast(self.wallgroup) self.collide = self.ray2.collisionany(self.wallgroup) print self.collide self.rectangles = [] if self.points != []: for point in self.points: rectangle = pygame.Rect(5, 5, 5, 5) rectangle.center = point self.rectangles.append(rectangle) self.rectangles2 = [] if self.points2 != []: for point in self.points2: rectangle = pygame.Rect(5, 5, 5, 5) rectangle.center = point self.rectangles2.append(rectangle) self.myLine = self.ray1.draw_ray() self.myLine2 = self.ray2.draw_ray() self.myLine3 = self.ray3.draw_ray() def draw(self): self.wallgroup.draw(self.surf) pygame.draw.line(self.surf, (255, 0, 255), self.myLine[0], self.myLine[1]) pygame.draw.line(self.surf, (255, 0, 255), self.myLine2[0], self.myLine2[1]) pygame.draw.line(self.surf, (255, 0, 255), self.myLine3[0], self.myLine3[1]) if self.rectangles != []: for recta in self.rectangles: pygame.draw.rect(self.surf, (255, 255, 0), recta) if self.rectangles2 != []: for recta in self.rectangles2: pygame.draw.rect(self.surf, (255, 255, 0), recta) self.screen.blit(self.surf, (0,0)) self.surf.fill((255, 255, 255)) def make_wall(self, size): self.wallgroup = pygame.sprite.LayeredDirty() x = y = 200 num = 1 for wall in xrange(size): wall = Tile((x,y), num) self.wallgroup.add(wall) x += 32 num += 1
def _raycast(self, pos, tar): ray = Ray(pos, tar) return ray.cast(self.mob.collision.current_floor.walls, 5)
clock = pygame.time.Clock() player = Player() font = pygame.font.SysFont("Arial", 18) def update_fps(): fps = str(int(clock.get_fps())) fps_text = font.render(fps, 1, pygame.Color("coral")) return fps_text # game loop while True: for event in pygame.event.get(): if event.type == pygame.QUIT: exit() player.move() screen.fill(BLACK) pygame.draw.rect(screen,SKY,(0,0,WIDTH,HEIGHT//2)) pygame.draw.rect(screen, GROUND, (0, HEIGHT//2, WIDTH, HEIGHT // 2)) Raycasting(screen,player) drawMinimap(screen, player, world_map,3) screen.blit(update_fps(), (10, 0)) pygame.display.flip() clock.tick(FPS)