Basic map editor finished.
This commit is contained in:
375
editor/editor.py
375
editor/editor.py
@@ -3,38 +3,397 @@
|
||||
# Copyright (c) 2014, Miguel Angel Astor Romero. All rights reserved.
|
||||
# See the file LICENSE for more details.
|
||||
|
||||
"""
|
||||
The map editor for TITLE PENDING, a game for the Cyberpunk Jam 2014.
|
||||
|
||||
Usage:
|
||||
*) Click on a game_map cell to set it's type.
|
||||
Use the keypad numbers to change the type of cell a cell will turn into
|
||||
when clicked. The active cell type is displayed on the title bar.
|
||||
|
||||
*) Left click to place an object on the game_map.
|
||||
Objects have to be edited by hand once the game_map has been saved. Use
|
||||
the keys 'd', 'k', 'p', 'n', 'e' and 'q' to set the active object type.
|
||||
The active object type is displayed on the title bar.
|
||||
|
||||
*) Press 'p' to set the player's starting position.
|
||||
|
||||
*) Press 's' to save the map to the text file 'map_file.map'. This will
|
||||
replace any previous map with the same name!
|
||||
|
||||
Press escape to quit.
|
||||
"""
|
||||
|
||||
import pygame
|
||||
|
||||
SCREEN_SIZE = (800, 600)
|
||||
TITLE = "Cyberpunk Jam 2014 - Level editor"
|
||||
FPS = 60
|
||||
CELL_SIZE = 10
|
||||
MAP_SIZE = (64, 64)
|
||||
SCREEN_SIZE = ((MAP_SIZE[1] * CELL_SIZE) + 1, (MAP_SIZE[0] * CELL_SIZE) + 1)
|
||||
SCREEN_FLAGS = pygame.HWSURFACE | pygame.DOUBLEBUF
|
||||
TITLE = "Cyberpunk Jam 2014 - Level editor"
|
||||
FPS = 60
|
||||
|
||||
# Cell types
|
||||
VOID = 0
|
||||
SOLID_WALL = 1
|
||||
SECRET_WALL = 2
|
||||
CLEAR_WALL = 3
|
||||
NEON_WALL = 4
|
||||
WINDOW_WALL = 5
|
||||
EMPTY_FLOOR = 6
|
||||
RUG = 7
|
||||
WATER = 8
|
||||
BAR = 9
|
||||
|
||||
# Object types
|
||||
DOOR = 0
|
||||
KEY = 1
|
||||
PERSON = 2
|
||||
PLAYER = 3
|
||||
EXIT = 4
|
||||
|
||||
def get_object_type_name(game_object):
|
||||
""" Return a string name for an object type. """
|
||||
name = ""
|
||||
if game_object == DOOR:
|
||||
name = "DOOR"
|
||||
elif game_object == KEY:
|
||||
name = "KEY"
|
||||
elif game_object == PERSON:
|
||||
name = "PERSON"
|
||||
elif game_object == PLAYER:
|
||||
name = "PLAYER"
|
||||
elif game_object == EXIT:
|
||||
name = "EXIT"
|
||||
elif game_object == None:
|
||||
name = "NONE"
|
||||
else:
|
||||
raise ValueError("Invalid object type.")
|
||||
|
||||
return name
|
||||
|
||||
def get_object_type_color(game_object):
|
||||
""" Return a string name for an object type. """
|
||||
color = (0, 0, 0)
|
||||
if game_object == DOOR:
|
||||
color = (255, 0, 255)
|
||||
elif game_object == KEY:
|
||||
color = (255, 255, 0)
|
||||
elif game_object == PERSON:
|
||||
color = (0, 255, 255)
|
||||
elif game_object == PLAYER:
|
||||
color = (128, 255, 0)
|
||||
elif game_object == EXIT:
|
||||
color = (255, 0, 255)
|
||||
else:
|
||||
raise ValueError("Invalid object type.")
|
||||
|
||||
return color
|
||||
|
||||
def get_floor_type_name(floor_type):
|
||||
""" Return a string name for a floor type. """
|
||||
name = ""
|
||||
|
||||
if floor_type == VOID:
|
||||
name = "VOID"
|
||||
elif floor_type == SOLID_WALL:
|
||||
name = "SOLID WALL"
|
||||
elif floor_type == SECRET_WALL:
|
||||
name = "SECRET WALL"
|
||||
elif floor_type == CLEAR_WALL:
|
||||
name = "CLEAR WALL"
|
||||
elif floor_type == NEON_WALL:
|
||||
name = "NEON WALL"
|
||||
elif floor_type == WINDOW_WALL:
|
||||
name = "WINDOW"
|
||||
elif floor_type == EMPTY_FLOOR:
|
||||
name = "EMPTY FLOOR"
|
||||
elif floor_type == RUG:
|
||||
name = "RUG"
|
||||
elif floor_type == WATER:
|
||||
name = "WATER"
|
||||
elif floor_type == BAR:
|
||||
name = "BAR"
|
||||
else:
|
||||
raise ValueError("Invalid floor type.")
|
||||
|
||||
return name
|
||||
|
||||
def get_floor_type_color(floor_type):
|
||||
""" Return a string name for a floor type. """
|
||||
color = (0, 0, 0)
|
||||
|
||||
if floor_type == VOID:
|
||||
color = (0, 0, 0)
|
||||
elif floor_type == SOLID_WALL:
|
||||
color = (255, 255, 255)
|
||||
elif floor_type == SECRET_WALL:
|
||||
color = (128, 128, 128)
|
||||
elif floor_type == CLEAR_WALL:
|
||||
color = (50, 50, 50)
|
||||
elif floor_type == NEON_WALL:
|
||||
color = (255, 0, 0)
|
||||
elif floor_type == WINDOW_WALL:
|
||||
color = (128, 128, 255)
|
||||
elif floor_type == EMPTY_FLOOR:
|
||||
color = (128, 128, 0)
|
||||
elif floor_type == RUG:
|
||||
color = (128, 0, 128)
|
||||
elif floor_type == WATER:
|
||||
color = (64, 64, 255)
|
||||
elif floor_type == BAR:
|
||||
color = (255, 255, 0)
|
||||
else:
|
||||
raise ValueError("Invalid floor type.")
|
||||
|
||||
return color
|
||||
|
||||
def save_map(game_map):
|
||||
p_id = 0
|
||||
dialogs = list()
|
||||
f = open("map_file.map", "w")
|
||||
|
||||
f.write("[MAP]\n")
|
||||
f.write(str(MAP_SIZE [0]) + " " + str(MAP_SIZE[1]) + "\n")
|
||||
for i in range(0, MAP_SIZE[0]):
|
||||
for j in range(0, MAP_SIZE[1]):
|
||||
f_t = game_map[i][j].get_type();
|
||||
f.write(str(f_t))
|
||||
f.write("\n")
|
||||
|
||||
f.write("[PLAYER]\n")
|
||||
f.write("%player = X Y\n")
|
||||
for i in range(0, MAP_SIZE[0]):
|
||||
for j in range(0, MAP_SIZE[1]):
|
||||
o_t = game_map[i][j].get_object();
|
||||
if o_t is not None and o_t == PLAYER:
|
||||
f.write("player = " + str(i) + " " + str(j) + "\n")
|
||||
|
||||
f.write("[EXITS]\n")
|
||||
f.write("%exit = X Y MAP_NAME MAP_X MAP_Y\n")
|
||||
for i in range(0, MAP_SIZE[0]):
|
||||
for j in range(0, MAP_SIZE[1]):
|
||||
o_t = game_map[i][j].get_object();
|
||||
if o_t is not None and o_t == EXIT:
|
||||
f.write("exit = " + str(i) + " " + str(j))
|
||||
f.write(" map_file.map 0 0\n")
|
||||
|
||||
f.write("[DOORS]\n")
|
||||
f.write("%door = X Y ID UNLOCKED\n")
|
||||
for i in range(0, MAP_SIZE[0]):
|
||||
for j in range(0, MAP_SIZE[1]):
|
||||
o_t = game_map[i][j].get_object();
|
||||
if o_t is not None and o_t == DOOR:
|
||||
f.write("door = " + str(i) + " " + str(j) + " 0" + " 0\n")
|
||||
|
||||
f.write("[KEYS]\n")
|
||||
f.write("%key = X Y ID\n")
|
||||
for i in range(0, MAP_SIZE[0]):
|
||||
for j in range(0, MAP_SIZE[1]):
|
||||
o_t = game_map[i][j].get_object();
|
||||
if o_t is not None and o_t == KEY:
|
||||
f.write("key = " + str(i) + " " + str(j) + " 0\n")
|
||||
|
||||
f.write("[PERSONS]\n")
|
||||
f.write("%person = X Y NAME DIALOG_ID\n")
|
||||
for i in range(0, MAP_SIZE[0]):
|
||||
for j in range(0, MAP_SIZE[1]):
|
||||
o_t = game_map[i][j].get_object();
|
||||
if o_t is not None and o_t == PERSON:
|
||||
f.write("person = " + str(i) + " " + str(j))
|
||||
f.write(" SOMEONE " + str(p_id) + "\n")
|
||||
dialogs.append(p_id)
|
||||
p_id += 1
|
||||
|
||||
f.write("[DIALOGS]\n")
|
||||
f.write("%dialog = ID TEXT\n")
|
||||
for id in dialogs:
|
||||
text = " Heavy boxes perform quick waltzes and jigs.\n"
|
||||
f.write("dialog = " + str(id) + text)
|
||||
|
||||
f.close()
|
||||
|
||||
class Cell:
|
||||
""" A game_map cell. """
|
||||
def __init__(self, x_size, y_size):
|
||||
""" Create a new cell. """
|
||||
self.x_size = x_size
|
||||
self.y_size = y_size
|
||||
|
||||
self.floor_type = VOID
|
||||
self.game_object = None
|
||||
|
||||
# Create the drawing rectangles.
|
||||
self.border = pygame.Rect((0, 0), (CELL_SIZE, CELL_SIZE))
|
||||
self.cell = pygame.Rect((0, 0), (CELL_SIZE - 2, CELL_SIZE - 2))
|
||||
|
||||
def set_type(self, floor_type):
|
||||
""" Set this cell floor type. Raises a value error if the type is
|
||||
not valid. """
|
||||
if floor_type < VOID or floor_type > BAR:
|
||||
raise ValueError("Floor type must be a number between 0 and 9.")
|
||||
else:
|
||||
self.floor_type = floor_type
|
||||
|
||||
def get_type(self):
|
||||
""" Returns this cell's type. """
|
||||
return self.floor_type
|
||||
|
||||
def set_object(self, game_object):
|
||||
""" Set this cells object. """
|
||||
if game_object is not None and game_object < DOOR or game_object > EXIT:
|
||||
raise ValueError("Object type must be a number between 0 and 2.")
|
||||
else:
|
||||
self.game_object = game_object
|
||||
|
||||
def get_object(self):
|
||||
""" Return this cell's object. """
|
||||
return self.game_object
|
||||
|
||||
def draw(self, canvas, x_pos, y_pos):
|
||||
""" Render this cell at the given position on the given screen. """
|
||||
self.border.center = (x_pos, y_pos)
|
||||
self.cell.center = (x_pos, y_pos)
|
||||
pygame.draw.rect(canvas, (0, 0, 255), self.border)
|
||||
|
||||
color = get_floor_type_color(self.floor_type)
|
||||
pygame.draw.rect(canvas, color, self.cell)
|
||||
|
||||
if self.game_object is not None and self.game_object < PLAYER:
|
||||
r = (CELL_SIZE - 2) // 2
|
||||
color = get_object_type_color(self.game_object)
|
||||
pygame.draw.circle(canvas, color, (x_pos, y_pos), r, 1)
|
||||
elif self.game_object is not None and self.game_object >= PLAYER:
|
||||
r = (CELL_SIZE - 3) // 2
|
||||
color = get_object_type_color(self.game_object)
|
||||
pygame.draw.circle(canvas, color, (x_pos, y_pos), r, 0)
|
||||
|
||||
def main():
|
||||
""" Application entry point. """
|
||||
# Local variables
|
||||
done = False
|
||||
game_map = list()
|
||||
curr_obj = None
|
||||
curr_fl = VOID
|
||||
obj_str = ""
|
||||
fl_str = ""
|
||||
mouse_pos = (0, 0)
|
||||
mouse_r_click = False
|
||||
mouse_l_click = False
|
||||
|
||||
# Initialize Pygame and pgs4a.
|
||||
# Initialize Pygame.
|
||||
pygame.init()
|
||||
clock = pygame.time.Clock()
|
||||
screen = pygame.display.set_mode(SCREEN_SIZE, pygame.HWSURFACE | pygame.DOUBLEBUF)
|
||||
pygame.mouse.set_visible(False)
|
||||
screen = pygame.display.set_mode(SCREEN_SIZE, SCREEN_FLAGS)
|
||||
pygame.mouse.set_visible(True)
|
||||
|
||||
for i in range(0, MAP_SIZE[0]):
|
||||
game_map.append([Cell(10, 10) for j in range(0, MAP_SIZE[1])])
|
||||
|
||||
# Main game loop.
|
||||
while(not done):
|
||||
try:
|
||||
fps = clock.get_fps() + 0.001
|
||||
pygame.display.set_caption(TITLE + ": " + str(int(fps)))
|
||||
|
||||
# Set title bar.
|
||||
obj_str = get_object_type_name(curr_obj)
|
||||
fl_str = get_floor_type_name(curr_fl)
|
||||
title = TITLE + " :: FPS: " + str(int(fps))
|
||||
title += " :: " + obj_str + " :: " + fl_str
|
||||
pygame.display.set_caption(title)
|
||||
|
||||
# Input capture.
|
||||
for event in pygame.event.get():
|
||||
if (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE) or event.type == pygame.QUIT:
|
||||
if event.type == pygame.QUIT:
|
||||
done = True
|
||||
|
||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||
mouse_pos = event.pos
|
||||
if event.button == 1:
|
||||
mouse_r_click = True
|
||||
elif event.button == 3:
|
||||
mouse_l_click = True
|
||||
|
||||
if event.type == pygame.MOUSEMOTION:
|
||||
if mouse_r_click:
|
||||
mouse_pos = event.pos
|
||||
|
||||
if event.type == pygame.MOUSEBUTTONUP:
|
||||
mouse_pos = event.pos
|
||||
if event.button == 1:
|
||||
mouse_r_click = False
|
||||
elif event.button == 3:
|
||||
mouse_l_click = False
|
||||
|
||||
if event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_ESCAPE:
|
||||
done = True
|
||||
|
||||
if event.key == pygame.K_d:
|
||||
curr_obj = DOOR
|
||||
if event.key == pygame.K_k:
|
||||
curr_obj = KEY
|
||||
if event.key == pygame.K_p:
|
||||
curr_obj = PERSON
|
||||
if event.key == pygame.K_q:
|
||||
curr_obj = PLAYER
|
||||
if event.key == pygame.K_e:
|
||||
curr_obj = EXIT
|
||||
if event.key == pygame.K_n:
|
||||
curr_obj = None
|
||||
|
||||
if event.key == pygame.K_0:
|
||||
curr_fl = VOID
|
||||
if event.key == pygame.K_1:
|
||||
curr_fl = SOLID_WALL
|
||||
if event.key == pygame.K_2:
|
||||
curr_fl = SECRET_WALL
|
||||
if event.key == pygame.K_3:
|
||||
curr_fl = CLEAR_WALL
|
||||
if event.key == pygame.K_4:
|
||||
curr_fl = NEON_WALL
|
||||
if event.key == pygame.K_5:
|
||||
curr_fl = WINDOW_WALL
|
||||
if event.key == pygame.K_6:
|
||||
curr_fl = EMPTY_FLOOR
|
||||
if event.key == pygame.K_7:
|
||||
curr_fl = RUG
|
||||
if event.key == pygame.K_8:
|
||||
curr_fl = WATER
|
||||
if event.key == pygame.K_9:
|
||||
curr_fl = BAR
|
||||
|
||||
if event.key == pygame.K_s:
|
||||
save_map(game_map)
|
||||
|
||||
# Update cycle.
|
||||
if mouse_r_click:
|
||||
i = mouse_pos[1] // CELL_SIZE
|
||||
j = mouse_pos[0] // CELL_SIZE
|
||||
if i >= MAP_SIZE[0]:
|
||||
i = MAP_SIZE[0] - 1
|
||||
if j >= MAP_SIZE[1]:
|
||||
j = MAP_SIZE[1] - 1
|
||||
game_map[i][j].set_type(curr_fl)
|
||||
|
||||
if mouse_l_click:
|
||||
i = mouse_pos[1] // CELL_SIZE
|
||||
j = mouse_pos[0] // CELL_SIZE
|
||||
if i >= MAP_SIZE[0]:
|
||||
i = MAP_SIZE[0] - 1
|
||||
if j >= MAP_SIZE[1]:
|
||||
j = MAP_SIZE[1] - 1
|
||||
game_map[i][j].set_object(curr_obj)
|
||||
|
||||
# Render cycle.
|
||||
screen.fill((0, 0, 0))
|
||||
|
||||
for i in range(0, MAP_SIZE[0]):
|
||||
for j in range(0, MAP_SIZE[1]):
|
||||
x = (j * CELL_SIZE) + (CELL_SIZE // 2)
|
||||
y = (i * CELL_SIZE) + (CELL_SIZE // 2)
|
||||
game_map[i][j].draw(screen, x, y)
|
||||
|
||||
pygame.display.update()
|
||||
clock.tick(FPS)
|
||||
|
||||
|
Reference in New Issue
Block a user