Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import math
- class Field:
- def __init__(self, width, height):
- self.width, self.height = width, height
- self.chars = [[' '] * height for i in range(width)]
- def fill(self, x1=' ', x2=-1, y1=-1, y2=-1, char=' '):
- if(type(x1) is str):
- self.chars = [[x1] * self.height for i in range(self.width)]
- elif(x2 > x1 and y2 > y1):
- for x in range(x1, x2):
- for y in range(y1, y2):
- self.chars[x][y] = char
- def overlay(self, x, y, source):
- for tx in range(x, min(self.width, source.width + x)):
- for ty in range(y, min(self.height, source.height + y)):
- if(source.chars[tx-x][ty-y] != ' '):
- self.chars[tx][ty] = source.chars[tx-x][ty-y]
- def draw(self, x, y, source):
- for tx in range(x, min(self.width, source.width + x)):
- for ty in range(y, min(self.height, source.height + y)):
- self.chars[tx][ty] = source.chars[tx-x][ty-y]
- def draw_string(self, x, y, string):
- for tx in range(x, min(x + len(string), self.width)):
- self.chars[tx][y] = string[tx-x]
- def draw_string_centered(self, x1, x2, y, string):
- x = (x2 - x1 - len(string)) // 2 + x1
- for tx in range(x, min(x + len(string), self.width - x)):
- self.chars[tx][y] = string[tx-x]
- def draw_box(self, x1, x2, y1, y2, charset='-|O'):
- if(len(charset) == 2):
- charset = charset[0] + charset[0] + charset[1]
- self.fill(x1, x2, y1, y1+1, charset[0])
- self.fill(x1, x2, y2, y2+1, charset[0])
- self.fill(x1, x1+1, y1, y2, charset[1])
- self.fill(x2, x2+1, y1, y2, charset[1])
- for cp in [(x1, y1), (x1, y2), (x2, y1), (x2, y2)]:
- self.draw_string(cp[0], cp[1], charset[2])
- def __str__(self):
- output = ''
- for y in range(self.height):
- output += ''.join([self.chars[i][y] for i in range(self.width)]) + '\n'
- return '\n' * 40 + output[:-1]
- def create_coordinate_border(in_width, in_height=0, title='', content=None):
- if(type(in_width) is Field):
- if(type(in_height) is str):
- title = in_height
- return create_coordinate_border(in_width.width, in_width.height, title=title, content=in_width)
- SPACING = 5
- side_margin = len(str(in_height)) + 1
- width = side_margin * 2 + in_width
- height = 4 + in_height
- if(title):
- height += 2
- output = Field(width, height)
- output.fill(' ')
- top_start = 0
- if(title):
- output.draw_box(side_margin-1, side_margin+in_width, 0, 2)
- output.draw_string_centered(side_margin, side_margin + in_width, 1, title)
- top_start += 2
- output.draw_box(side_margin-1, side_margin+in_width, top_start, top_start+2)
- output.draw_box(side_margin-1, side_margin+in_width, top_start+2, height-1)
- for x in range(0, in_width, SPACING):
- output.draw_string(x - len(str(x)) + side_margin + 1, top_start + 1, str(x))
- output.draw_string(x + side_margin, top_start + 2, '+')
- for y in range(0, in_height, SPACING):
- output.draw_string(side_margin - len(str(y)) - 1, y + top_start + 3, str(y))
- output.draw_string(side_margin + in_width + 1, y + top_start + 3, str(y))
- output.draw_string(side_margin - 1, y + top_start + 3, '+')
- output.draw_string(side_margin + in_width, y + top_start + 3, '+')
- if(content):
- output.draw(side_margin, 3 + top_start, content)
- return output
- from math import ceil
- def render_tabulated_grid(width, items=[]):
- if(len(items) == 0):
- return Field(width, 0)
- maxlen = max([len(i) + 2 for i in items])
- tablen = min([i for i in range(maxlen, width) if width % i <= 4])
- columns = width // tablen
- height = ceil(len(items) / columns)
- output = Field(width, height)
- for y in range(0, height):
- for x in range(0, columns):
- index = x + y * columns
- if(index < len(items)):
- output.draw_string(x * tablen, y, items[index])
- return output
- class Interface:
- def __init__(self):
- self.output = None
- def get_controls(self):
- return []
- def get_title(self):
- return ''
- def get_status(self):
- return Field(0, 0)
- def render(self):
- window_content = self.get_main()
- title = self.get_title()
- controls = self.get_controls()
- status_content = self.get_status()
- width = window_content.width + 2
- inset = 0
- height = window_content.height + 2
- if(title):
- height += 2
- control_pane = render_tabulated_grid(width - 2, controls)
- height += status_content.height + 1 + control_pane.height + 1
- output = Field(width, height)
- y = 0
- if(title):
- output.draw_box(0, width-1, y, y+2)
- output.draw_string((width - len(title)) // 2, 1, title)
- y += 2
- output.draw_box(0, width-1, y, window_content.height+1+y)
- output.draw(1, y+1, window_content)
- y += window_content.height + 1
- output.draw_box(0, width-1, y, y+status_content.height+1)
- output.draw(1, y + 1, status_content)
- y += status_content.height + 1
- output.draw_box(0, width-1, y, y+control_pane.height+1)
- output.draw(1, y + 1, control_pane)
- self.output = output
- def update(self, delta_time):
- pass
- def on_key(self, key_code):
- pass
- def __str__(self):
- if(not self.output):
- self.render()
- return str(self.output)
- from random import randint
- '''
- useful unicode characters:
- ֍ ܔ ௬ ௐ ౠ གྷ ࿐ ᑐ ᗘ
- '''
- class UniverseObject:
- def __init__(self, char):
- self.char = char
- self.explored = False
- def __str__(self):
- if(self.explored):
- return self.char
- else:
- return '?'
- class EmptySpace(UniverseObject):
- def __init__(self):
- super().__init__(' ')
- class Star(UniverseObject):
- def __init__(self):
- super().__init__('*')
- UNIVERSE_WIDTH = 121
- UNIVERSE_HEIGHT = 41
- universe = [[EmptySpace() for j in range(UNIVERSE_HEIGHT)] for i in range(UNIVERSE_WIDTH)]
- for x in range(UNIVERSE_WIDTH):
- for y in range(UNIVERSE_HEIGHT):
- # 30% chance of a star
- if(randint(0, 100) <= 10):
- universe[x][y] = Star()
- class Ship:
- def __init__(self, x, y):
- self.x, self.y = x, y
- def __str__(self):
- return '+'
- def explore(self, radius):
- ir = int(radius)
- for x in range(-ir*2, ir*2+1):
- for y in range(-ir, ir+1):
- if(math.sqrt((x/2)**2 + y**2) <= radius + 0.5):
- print(x, y)
- print(x + self.x, y + self.y)
- universe[x+self.x][y+self.y].explored = True
- def short_range_scan(self):
- self.explore(1)
- def long_range_scan(self):
- self.explore(6)
- def fly_to(self, x, y):
- self.x, self.y = x, y
- print(x, y)
- self.short_range_scan()
- ship = Ship(60, 20)
- ship.long_range_scan()
- crosshair = Field(3, 3)
- crosshair.draw_string(0, 0, '\\ /')
- crosshair.draw_string(0, 2, '/ \\')
- SCREEN_WIDTH = 121
- SCREEN_HEIGHT = 41
- class StarMap(Interface):
- def __init__(self):
- super().__init__()
- self.cx, self.cy = 0, 0
- def get_title(self):
- return 'UNIVERSE MAP'
- def get_controls(self):
- return ['WASD: Navigate', 'SHIFT: Navigate Faster', 'SPACE: Fly To', 'Z: Long Range Scan', 'Q: Exit Game']
- def get_main(self):
- global universe
- f = Field(SCREEN_WIDTH, SCREEN_HEIGHT)
- for y in range(SCREEN_HEIGHT):
- for x in range(SCREEN_WIDTH):
- ux = (x + self.cx + UNIVERSE_WIDTH) % UNIVERSE_WIDTH
- uy = (y + self.cy + UNIVERSE_HEIGHT) % UNIVERSE_HEIGHT
- if(universe[ux][uy]):
- f.draw_string(x, y, str(universe[ux][uy]))
- f.overlay(SCREEN_WIDTH // 2 - 1, SCREEN_HEIGHT // 2 - 1, crosshair)
- f.draw_string(ship.x - self.cx, ship.y - self.cy, str(ship))
- return f
- def on_key(self, key):
- global going, ship
- key = key.decode('ascii')
- amount = [1, 10][key != key.lower()]
- key = key.lower()
- if(key == 'w'):
- self.cy -= amount
- elif(key == 'a'):
- self.cx -= amount
- elif(key == 's'):
- self.cy += amount
- elif(key == 'd'):
- self.cx += amount
- elif(key == ' '):
- ship.fly_to(self.cx + SCREEN_WIDTH // 2, self.cy + SCREEN_HEIGHT // 2)
- elif(key == 'z'):
- ship.long_range_scan()
- elif(key == 'q'):
- going = False
- self.cx = (self.cx + UNIVERSE_WIDTH) % UNIVERSE_WIDTH
- self.cy = (self.cy + UNIVERSE_HEIGHT) % UNIVERSE_HEIGHT
- def get_status(self):
- return render_tabulated_grid(81, ['Hull: 100%', 'Fuel: 100%'])
- from msvcrt import getch as getkey
- from time import sleep, time
- cint = StarMap()
- print(cint)
- last = time()
- going = True
- while going:
- kc = getkey()
- #print(kc)
- #continue
- if(kc == b'\xff'):
- sleep(0.02)
- continue
- else:
- cint.on_key(kc)
- cint.update(time() - last)
- last = time()
- cint.render()
- print(cint)
- sleep(0.02)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement