import curses
import random
import time
import math
# ---------- GLOBAL SETTINGS ----------
WORLD_WIDTH = 150
WORLD_HEIGHT = 50
SCREEN_WIDTH = 30
SCREEN_HEIGHT = 15
# Block symbols
AIR = ' '
GRASS = 'G'
DIRT = 'D'
STONE = 'S'
WOOD = 'W'
LEAF = 'L'
OBSIDIAN = 'O'
FURNACE_BLK = 'F'
# Colors (if terminal supports)
# (You can later add color attributes with curses.init_pair)
# ---------- PLAYER & ENEMY CLASSES ----------
# The player’s displayed symbol will change based on orientation.
# We map an angle (in degrees) to one of four characters.
def get_direction_symbol(angle):
# Normalize angle to [0,360)
angle = angle % 360
if angle < 45 or angle >= 315:
return ">" # facing right
elif angle < 135:
return "^" # facing up
elif angle < 225:
return "<" # facing left
else:
return "v" # facing down
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
self.health = 100
self.inventory = {"wood": 0, "cobblestone": 0} # expand as needed
self.orientation = 0 # angle in degrees, default 0 (right)
player = Player(WORLD_WIDTH // 2, WORLD_HEIGHT // 2)
# Define enemy types in Minecraft style.
# Each enemy is a dict with x, y, health and a symbol.
enemy_types = [
{"type": "zombie", "symbol": "Z", "health": 20},
{"type": "skeleton", "symbol": "S", "health": 15},
{"type": "creeper", "symbol": "C", "health": 10},
{"type": "enderman", "symbol": "E", "health": 25}
]
enemies = [] # list of enemy dictionaries
# ---------- WORLD GENERATION ----------
def generate_world():
world = [[AIR for _ in range(WORLD_WIDTH)] for _ in range(WORLD_HEIGHT)]
ground_level = WORLD_HEIGHT - 10
for y in range(WORLD_HEIGHT):
for x in range(WORLD_WIDTH):
if y < ground_level - 2:
world[y][x] = AIR
elif y < ground_level:
world[y][x] = DIRT
elif y == ground_level:
world[y][x] = GRASS
else:
world[y][x] = STONE
# Build some trees in the “safe” starter area (for x roughly less than 50)
for _ in range(10):
tx = random.randint(5, 50)
ty = ground_level - 1
# Tree trunk (wood)
for h in range(3):
if ty - h >= 0:
world[ty - h][tx] = WOOD
# Leaves around the top
for dx in range(-1, 2):
for dy in range(-2, 1):
if 0 <= tx + dx < WORLD_WIDTH and 0 <= ty - 3 + dy < WORLD_HEIGHT:
if random.random() < 0.6:
world[ty - 3 + dy][tx + dx] = LEAF
return world
world = generate_world()
# ---------- DRAWING FUNCTION WITH CAMERA ----------
def draw_game(stdscr):
stdscr.clear()
# Compute camera offset: center the viewport around the player
cam_x = max(0, min(player.x - SCREEN_WIDTH // 2, WORLD_WIDTH - SCREEN_WIDTH))
cam_y = max(0, min(player.y - SCREEN_HEIGHT // 2, WORLD_HEIGHT - SCREEN_HEIGHT))
# Draw the world (each block)
for y in range(SCREEN_HEIGHT):
for x in range(SCREEN_WIDTH):
ch = world[cam_y + y][cam_x + x]
stdscr.addch(y, x, ch)
# Draw enemies if they are visible
for enemy in enemies:
ex, ey = enemy["x"], enemy["y"]
if cam_x <= ex < cam_x + SCREEN_WIDTH and cam_y <= ey < cam_y + SCREEN_HEIGHT:
stdscr.addch(ey - cam_y, ex - cam_x, enemy["symbol"])
# Draw the player using an orientation–dependent symbol
player_sym = get_direction_symbol(player.orientation)
if cam_x <= player.x < cam_x + SCREEN_WIDTH and cam_y <= player.y < cam_y + SCREEN_HEIGHT:
stdscr.addch(player.y - cam_y, player.x - cam_x, player_sym, curses.A_BOLD)
# Display status info below the viewport
status = "Health: {} Pos: ({}, {})".format(player.health, player.x, player.y)
stdscr.addstr(SCREEN_HEIGHT, 0, status)
inv_str = "Inventory: " + str(player.inventory)
stdscr.addstr(SCREEN_HEIGHT + 1, 0, inv_str)
prompt = "WASD: move, Mouse: aim, I: inventory, Q: quit"
stdscr.addstr(SCREEN_HEIGHT + 2, 0, prompt)
stdscr.refresh()
# ---------- PLAYER MOVEMENT & GRAVITY ----------
def update_player_position(key):
# Move the player with WASD
if key == ord('w'):
if player.y > 0 and world[player.y - 1][player.x] == AIR:
player.y -= 1
elif key == ord('s'):
if player.y < WORLD_HEIGHT - 1 and world[player.y + 1][player.x] == AIR:
player.y += 1
elif key == ord('a'):
if player.x > 0 and world[player.y][player.x - 1] == AIR:
player.x -= 1
elif key == ord('d'):
if player.x < WORLD_WIDTH - 1 and world[player.y][player.x + 1] == AIR:
player.x += 1
# Simple gravity: if below is AIR, fall down
if player.y < WORLD_HEIGHT - 1 and world[player.y + 1][player.x] == AIR:
player.y += 1
# ---------- ENEMY SPAWN &