Your cart is currently empty!
Raycasting in PyGame V0.1
I have been wanting to experiment with different methods of input for machine learning in games. I know raycasting can be a fairly effective method of detecting nearby objects for the AI player so I wanted to see if I could get that working in PyGame. It is nowhere near perfect but for a first attempt I'd say it is a modest success in achieving the basics at least.
import pygame
import math
import random
import sys
#VARS
RAY_RANGE = 150
RAY_ANGLE = 10
#Class for the pyGame Window
class gameWindow:
def __init__(self, width, height):
self.width = width
self.height = height
self.screen = pygame.display.set_mode((self.width, self.height))
self.clock = pygame.time.Clock()
self.fps = 60
def update(self):
pygame.display.update()
self.clock.tick(self.fps)
def draw_background(self, color=(0,0,0)):
self.screen.fill(color)
def draw_text(self, text, font, color, x, y):
text_obj = font.render(text, 1, color)
self.screen.blit(text_obj, (x, y))
def handle_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
#Class for the player
class Player:
def __init__(self, x, y, speed, color):
self.x = x
self.y = y
self.speed = speed
self.color = color
self.width = 50
self.height = 50
def draw(self, gameWindow):
pygame.draw.rect(gameWindow.screen, self.color, pygame.Rect(self.x, self.y, self.width, self.height))
def move(self, direction):
if direction == 'up':
self.y -= self.speed
elif direction == 'down':
self.y += self.speed
elif direction == 'left':
self.x -= self.speed
elif direction == 'right':
self.x += self.speed
def raycast(self, angle, obj, range):
ray = Ray((self.x, self.y), angle)
intersection = ray.cast(obj, range)
return intersection
class Ray:
def __init__(self, origin, angle):
self.origin = pygame.math.Vector2(origin)
self.dir = pygame.math.Vector2(math.cos(angle), math.sin(angle))
def cast(self, obj, ray_range):
t_near = float('-inf')
t_far = float('inf')
for i in range(2):
if abs(self.dir[i]) < 1e-8:
if self.origin[i] < obj.rect.topleft[i] or self.origin[i] > obj.rect.bottomright[i]:
return None
else:
t1 = (obj.rect.topleft[i] - self.origin[i]) / self.dir[i]
t2 = (obj.rect.bottomright[i] - self.origin[i]) / self.dir[i]
if t1 > t2:
t1, t2 = t2, t1
if t1 > t_near:
t_near = t1
if t2 < t_far:
t_far = t2
if t_near > t_far or t_far < 0:
return None
intersection = self.origin + self.dir * t_near
if (intersection - self.origin).length() > ray_range:
return None
#print length of ray
print((intersection - self.origin).length())
#print which object is hit
print(obj)
return intersection
class Object:
def __init__(self, x, y, width, height, color):
self.rect = pygame.Rect(x, y, width, height)
self.color = color
def draw(self, gameWindow):
pygame.draw.rect(gameWindow.screen, self.color, self.rect)
# Initialize Pygame
pygame.init()
# Create a game window
window = gameWindow(800, 600)
# Create some objects
objects = []
for _ in range(10): # Generate 10 objects
x = random.randint(0, window.width - 50)
y = random.randint(0, window.height - 50)
color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
objects.append(Object(x, y, 50, 50, color))
# Create a player
player = Player(400, 300, 5, (255, 255, 255))
# Game loop
while True:
window.handle_events()
# Update game state
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
player.move('up')
if keys[pygame.K_DOWN]:
player.move('down')
if keys[pygame.K_LEFT]:
player.move('left')
if keys[pygame.K_RIGHT]:
player.move('right')
# Draw game state
window.draw_background()
player.draw(window)
# draw ray cast from player to each object
for obj in objects:
obj.draw(window)
for angle in range(0, 360, RAY_ANGLE):
intersection = player.raycast(math.radians(angle), obj, RAY_RANGE)
if intersection is not None:
pygame.draw.line(window.screen, (255, 255, 255), (player.x+(player.width/2), player.y+(player.height/2)), intersection)
window.update()
Leave a Reply