graphics: Generate the HELP screen programatically.

The original Doom HELP screen showed the default key bindings for the
game's controls. This is not so useful nowadays: at worst it's
outright misleading because the player might not be using the
defaults, but it's also redundant because most modern source ports
allow the key bindings to be changed via the menus, which doubles as a
convenient list of the current key bindings.

Z0k suggested an alternative HELP screen that shows the items and
powerups available in the game. More discussion can be seen in this
thread: http://www.doomworld.com/vb/freedoom/69458-help/
This commit is contained in:
Simon Howard 2014-07-27 03:28:14 +00:00
parent fa4d3b9a2d
commit 18be2c988c
6 changed files with 284 additions and 16 deletions

View file

@ -3,6 +3,10 @@ wi*.gif
wilv*.gif
cwilv*.gif
dmwilv*.gif
help*.gif
helpbg.png
help.gif
helpoverlay.png
helptext.png
helpttl.gif
prboom.gif
graphics.stamp

View file

@ -55,14 +55,79 @@ graphics.stamp: config.py fontchars ../../lumps/fraggle/freedoom.bex
./textgen
@mv graphics.tmp $@
help.gif: helpbg.gif helptext.gif helpttl.gif
convert helpbg.gif \
-draw 'image over 0,0 0,0 helptext.gif' \
-draw 'image over 140,5 0,0 helpttl.gif' \
# Generate transparent image containing text for the HELP screen:
helptext.png:
python smtextgen helptext.png 320x200 \
10,25 "Weapons" \
10,67 "Ammo" \
110,67 "Shells" \
220,67 "Backpack" \
10,90 "Missiles" \
170,90 "Energy" \
10,115 "Health" \
170,115 "Armor" \
145,140 "Map" \
10,140 "Overdrive" \
10,163 "Night vis" \
10,182 "Invisibility" \
135,182 "Invuln" \
255,182 "Keys" \
130,163 "Hazard suit"
# Build on helptext.png by adding the title and sprites:
helpoverlay.png : helptext.png helpttl.gif
convert helptext.png \
-draw 'image over 150,5 0,0 "helpttl.gif"' \
-draw 'image over 80,25 0,0 "../../sprites/shota0.gif"' \
-draw 'image over 150,25 0,0 "../../sprites/sgn2a0.gif"' \
-draw 'image over 210,20 0,0 "../../sprites/mguna0.gif"' \
-draw 'image over 10,40 0,0 "../../sprites/launa0.gif"' \
-draw 'image over 80,40 0,0 "../../sprites/plasa0.gif"' \
-draw 'image over 150,40 0,0 "../../sprites/bfuga0.gif"' \
-draw 'image over 240,40 0,0 "../../sprites/csawa0.gif"' \
-draw 'image over 53,67 0,0 "../../sprites/clipa0.gif"' \
-draw 'image over 68,62 0,0 "../../sprites/ammoa0.gif"' \
-draw 'image over 160,67 0,0 "../../sprites/shela0.gif"' \
-draw 'image over 180,62 0,0 "../../sprites/sboxa0.gif"' \
-draw 'image over 76,78 0,0 "../../sprites/rocka0.gif"' \
-draw 'image over 95,82 0,0 "../../sprites/broka0.gif"' \
-draw 'image over 220,90 0,0 "../../sprites/cella0.gif"' \
-draw 'image over 240,81 0,0 "../../sprites/celpa0.gif"' \
-draw 'image over 290,55 0,0 "../../sprites/bpaka0.gif"' \
-draw 'image over 63,113 0,0 "../../sprites/bon1a0.gif"' \
-draw 'image over 78,112 0,0 "../../sprites/stima0.gif"' \
-draw 'image over 96,107 0,0 "../../sprites/media0.gif"' \
-draw 'image over 128,107 0,0 "../../sprites/pstra0.gif"' \
-draw 'image over 220,113 0,0 "../../sprites/bon2a0.gif"' \
-draw 'image over 240,105 0,0 "../../sprites/arm1b0.gif"' \
-draw 'image over 280,105 0,0 "../../sprites/arm2b0.gif"' \
-draw 'image over 175,130 0,0 "../../sprites/pmapa0.gif"' \
-draw 'image over 84,132 0,0 "../../sprites/soula0.gif"' \
-draw 'image over 110,132 0,0 "../../sprites/megaa0.gif"' \
-draw 'image over 80,160 0,0 "../../sprites/pvisa0.gif"' \
-draw 'image over 100,172 0,0 "../../sprites/pinsa0.gif"' \
-draw 'image over 185,174 0,0 "../../sprites/pinva0.gif"' \
-draw 'image over 246,142 0,0 "../../sprites/rkeya0.gif"' \
-draw 'image over 261,142 0,0 "../../sprites/ykeya0.gif"' \
-draw 'image over 276,142 0,0 "../../sprites/bkeya0.gif"' \
-draw 'image over 246,162 0,0 "../../sprites/rskua0.gif"' \
-draw 'image over 261,162 0,0 "../../sprites/yskua0.gif"' \
-draw 'image over 276,162 0,0 "../../sprites/bskua0.gif"' \
-draw 'image over 215,142 0,0 "../../sprites/suita0.gif"' \
-transparent '#00ffff' \
helpoverlay.png
# Background for the help screen is a color shifted version of INTERPIC:
helpbg.png: ../interpic.gif
convert ../interpic.gif -fill '#5599ff' -tint 100 helpbg.png
# Draw the overlay with text and sprites onto the background to get the
# HELP screen:
help.gif: helpbg.png helpoverlay.png
convert helpbg.png \
-draw 'image over 0,0 0,0 helpoverlay.png' \
help.gif
helpbg.gif: ../interpic.gif
convert ../interpic.gif -fill '#0077ff' -tint 50 helpbg.gif
clean:
rm -f $(TEXTGEN_GRAPHICS) helpbg.gif help.gif graphics.stamp *.pyc
rm -f $(TEXTGEN_GRAPHICS) helpbg.png help.gif \
helpoverlay.png helptext.png graphics.stamp *.pyc

View file

@ -107,6 +107,9 @@ blue_graphics = {
}
red_graphics = {
# Title for the HELP/HELP1 screen:
'helpttl': 'Help',
'm_ngame': 'New Game',
'm_option': 'Options',
'm_loadg': 'Load Game',
@ -216,12 +219,6 @@ red_graphics = {
'm_multi': 'Multiplayer',
}
# Rendered with transparent background:
transparent_graphics = {
# Title for the HELP/HELP1 screen:
'helpttl': 'Help',
}
def read_bex_lump(filename):
"""Read the BEX (Dehacked) lump from the given filename.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

203
graphics/text/smtextgen Executable file
View file

@ -0,0 +1,203 @@
#!/usr/bin/env python
#
# Copyright (c) 2014
# Contributors to the Freedoom project. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the freedoom project nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ----------------------------------------------------------------------
#
# Script to generate text graphics using the "small" (HUD) font.
#
from glob import glob
import sys
import subprocess
import re
# ImageMagick commands used by this script:
CONVERT_COMMAND = 'convert'
IDENTIFY_COMMAND = 'identify'
# Background color for output files.
BACKGROUND_COLOR = '#00ffff'
# Width of a space character in pixels.
SPACE_WIDTH = 4
# Height of the font.
FONT_HEIGHT = 7
# Regexp to match dimensions/x,y coordinate pair.
DIMENSION_MATCH_RE = re.compile(r'(\d+)[x,](\d+)')
# Output from 'identify' looks like this:
# fontchars/font033.gif GIF 9x16 9x16+0+0 8-bit sRGB 32c 194B 0.000u 0:00.000
IDENTIFY_OUTPUT_RE = re.compile(r'(\S+)\s(\S+)\s(\d+)x(\d+)\s')
def get_image_dimensions(filename):
proc = subprocess.Popen([IDENTIFY_COMMAND, filename],
stdout=subprocess.PIPE)
proc.wait()
line = proc.stdout.readline().decode('utf-8')
match = IDENTIFY_OUTPUT_RE.match(line)
assert match is not None
return (int(match.group(3)), int(match.group(4)))
def invoke_command(command):
"""Invoke a command, printing the command to stdout.
Args:
command: Command and arguments as a list.
"""
for arg in command:
if arg.startswith('-'):
sys.stdout.write("\\\n ")
if ' ' in arg or '#' in arg:
sys.stdout.write(repr(arg))
else:
sys.stdout.write(arg)
sys.stdout.write(' ')
sys.stdout.write('\n')
return subprocess.call(command)
class Font(object):
def __init__(self):
self.get_font_widths()
def compile_kerning_table(self, kerning_table):
"""Given a dictionary of kerning patterns, compile Regexps."""
result = {}
for pattern, adjust in kerning_table.items():
result[re.compile(pattern)] = adjust
return result
def get_font_widths(self):
charfiles = glob('../stcfn*.gif')
self.char_widths = {}
for c in range(128):
filename = self.char_filename(chr(c))
if filename not in charfiles:
continue
w, _ = get_image_dimensions(filename)
self.char_widths[chr(c)] = w
def __contains__(self, c):
return c in self.char_widths
def char_width(self, c):
return self.char_widths[c]
def char_filename(self, c):
return '../stcfn%03d.gif' % (ord(c))
def draw_commands_for_text(self, text, x, y):
text = text.upper()
result = []
x1, y1 = x, y
for c in text:
if c == '\n':
y1 += FONT_HEIGHT
x1 = x
elif c == ' ':
x1 += SPACE_WIDTH
if c not in self:
continue
filename = self.char_filename(c)
result.extend([
'-draw',
'image over %i,%i 0,0 "%s"' %
(x1, y1, filename)
])
x1 += self.char_width(c)
return result
def parse_command_line(args):
if len(args) < 4 or (len(args) % 2) != 0:
return None
result = {
'filename': args[0],
'strings': [],
}
m = DIMENSION_MATCH_RE.match(args[1])
if not m:
return None
result['dimensions'] = (int(m.group(1)), int(m.group(2)))
i = 2
while i < len(args):
m = DIMENSION_MATCH_RE.match(args[i])
if not m:
return None
xy = (int(m.group(1)), int(m.group(2)))
result['strings'].append((xy, args[i + 1]))
i += 2
return result
args = parse_command_line(sys.argv[1:])
if not args:
print "Usage: smtextgen <filename> <size> [...text commands...]"
print "Where each text command looks like:"
print " [x,y] [text]"
sys.exit(0)
smallfont = Font()
command_line = [
CONVERT_COMMAND,
'-size', '%ix%i' % args['dimensions'],
'xc:none',
]
for xy, string in args['strings']:
command_line.extend(smallfont.draw_commands_for_text(
string, xy[0], xy[1]))
command_line.extend((
'-background', BACKGROUND_COLOR,
'-flatten', args['filename'],
))
invoke_command(command_line)

View file

@ -249,5 +249,4 @@ font = Font('fontchars', kerning_table=FONT_KERNING_RULES)
generate_graphics(red_graphics, color=COLOR_RED)
generate_graphics(blue_graphics, color=COLOR_BLUE)
generate_graphics(white_graphics, color=COLOR_WHITE)
generate_graphics(transparent_graphics, color=COLOR_RED, bgcolor=None)