Created
June 19, 2025 01:42
-
-
Save EncodeTheCode/27ade2389694681d7652b60ec33637e2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pygame, sys, math | |
pygame.init() | |
screen = pygame.display.set_mode((800, 600)) | |
clock = pygame.time.Clock() | |
# Colors | |
WHITE = (255,255,255); BLACK = (0,0,0); GRAY = (50,50,50) | |
BLUE = (0, 128, 255); RED = (200, 0, 0); YELLOW = (255, 255, 0); GREEN = (0,200,0); ORANGE = (255,165,0) | |
# Simple player and enemy classes | |
class Player: | |
def __init__(self,x,y): | |
self.pos = pygame.math.Vector2(x,y) | |
self.radius = 10 | |
def draw(self,surf): pygame.draw.circle(surf, GREEN, (int(self.pos.x),int(self.pos.y)), self.radius) | |
class Enemy: | |
def __init__(self,x,y,angle_deg=0): | |
self.pos = pygame.math.Vector2(x,y) | |
self.facing_angle = angle_deg # in degrees, 0 = right | |
self.radius = 12 | |
def draw(self,surf): | |
# Draw enemy as an oriented triangle | |
ang = math.radians(self.facing_angle) | |
pts = [] | |
for theta in [0, 2.5, -2.5]: | |
dx = math.cos(ang+theta)*self.radius | |
dy = math.sin(ang+theta)*self.radius | |
pts.append((self.pos.x+dx, self.pos.y+dy)) | |
pygame.draw.polygon(surf, ORANGE, pts) | |
def is_aiming_at(self,player): | |
# Check if player is roughly in front of enemy (simple dot-product check) | |
forward = pygame.math.Vector2(math.cos(math.radians(self.facing_angle)), | |
math.sin(math.radians(self.facing_angle))) | |
to_player = (player.pos - self.pos) | |
if to_player.length() == 0: return False | |
dot = forward.dot(to_player.normalize()) | |
return dot > 0.7 | |
class Obstacle: | |
def __init__(self,x,y,w,h): | |
self.rect = pygame.Rect(x,y,w,h) | |
def draw(self,surf): pygame.draw.rect(surf, (128,128,128), self.rect) | |
# Line-of-sight check (raycast vs obstacles) | |
def line_of_sight(enemy, player, obstacles): | |
e = (enemy.pos.x, enemy.pos.y) | |
p = (player.pos.x, player.pos.y) | |
for obs in obstacles: | |
if obs.rect.clipline(e,p): # If the line intersects the obstacle | |
return False | |
return True | |
# Instantiate objects | |
player = Player(50, 300) | |
enemy = Enemy(100, 300, angle_deg=0) # Enemy facing right | |
obstacles = [Obstacle(300, 200, 50, 300)] # One blocking wall | |
# Player stats | |
max_armor = 100; armor = max_armor | |
max_health = 100; health = max_health | |
# Danger meter | |
danger = 0.0 | |
max_danger = 100.0 | |
danger_rate = 30.0 # fill speed | |
blink = False | |
blink_time = 0.0 | |
font = pygame.font.SysFont(None, 24) | |
running = True | |
while running: | |
dt = clock.tick(60) / 1000.0 | |
for ev in pygame.event.get(): | |
if ev.type == pygame.QUIT: running=False | |
if ev.type == pygame.KEYDOWN: | |
if ev.key == pygame.K_ESCAPE: running=False | |
if ev.key == pygame.K_h: | |
# Simulate damage: reduce armor or health | |
if armor > 0: armor = max(0, armor-20) | |
else: health = max(0, health-20) | |
# Player movement | |
keys = pygame.key.get_pressed() | |
speed = 150 * dt | |
if keys[pygame.K_LEFT]: player.pos.x -= speed | |
if keys[pygame.K_RIGHT]: player.pos.x += speed | |
if keys[pygame.K_UP]: player.pos.y -= speed | |
if keys[pygame.K_DOWN]: player.pos.y += speed | |
# Danger logic: is enemy targeting player with clear LOS? | |
if enemy.is_aiming_at(player) and line_of_sight(enemy, player, obstacles): | |
danger = min(max_danger, danger + danger_rate*dt) | |
else: | |
# Reset meter when not targeted:contentReference[oaicite:21]{index=21} | |
danger = 0.0 | |
blink = False; blink_time = 0.0 | |
# Blink if danger is full | |
if danger >= max_danger: | |
blink_time += dt | |
if blink_time >= 0.5: | |
blink_time = 0.0 | |
blink = not blink | |
# -- Drawing -- | |
screen.fill(BLACK) | |
for obs in obstacles: obs.draw(screen) | |
player.draw(screen) | |
enemy.draw(screen) | |
# Draw Armor bar (blue for armor, then red for health) | |
bar_x, bar_y = 10, 10 | |
bar_w, bar_h = 200, 20 | |
pygame.draw.rect(screen, GRAY, (bar_x, bar_y, bar_w, bar_h)) # background | |
# Armor portion | |
arm_w = int(bar_w * (armor/max_armor)) | |
pygame.draw.rect(screen, BLUE, (bar_x, bar_y, arm_w, bar_h)) | |
# If armor is depleted, draw health in red | |
if armor == 0: | |
health_w = int(bar_w * (health/max_health)) | |
pygame.draw.rect(screen, RED, (bar_x, bar_y, health_w, bar_h)) | |
pygame.draw.rect(screen, WHITE, (bar_x, bar_y, bar_w, bar_h), 2) | |
health_text = font.render(f"Armor:{armor}/{max_armor} Health:{health}/{max_health}", True, WHITE) | |
screen.blit(health_text, (bar_x, bar_y+bar_h+5)) | |
# Draw Danger meter below (yellow fill) | |
d_x, d_y = 10, 50 | |
d_w, d_h = 200, 15 | |
pygame.draw.rect(screen, GRAY, (d_x, d_y, d_w, d_h)) | |
fill_w = int(d_w * (danger/max_danger)) | |
# If blinking off, skip drawing the fill | |
if fill_w > 0 and not blink: | |
pygame.draw.rect(screen, YELLOW, (d_x, d_y, fill_w, d_h)) | |
pygame.draw.rect(screen, WHITE, (d_x, d_y, d_w, d_h), 2) | |
danger_text = font.render("Danger Meter", True, WHITE) | |
screen.blit(danger_text, (d_x, d_y-20)) | |
# Instructions | |
instr = font.render("Arrow keys to move, H = take damage", True, WHITE) | |
screen.blit(instr, (10, 580)) | |
pygame.display.flip() | |
pygame.quit() | |
sys.exit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment