Please login or register.

Login with username, password and session length
Advanced search  


[2014/08/29] New steam profile field added. Add your steam ID now. Join the FFHacktics steam group.

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - lirmont

Pages: [1] 2 3 ... 24
Tethical / FFT-Like Music
« on: September 10, 2014, 09:03:47 AM »
Main composition: Heat of the Moment (1:20).
Background music for this thread: Heat of the Moment (16:24).

So, some of you may be aware that I sunk a month into investigating FFT's music, including being able to replace the waveforms (essentially *.WAV files). I did this because I got to a point in developing the demos for the Kickstarter relaunch where I realized the music just didn't match with the quality of the graphics. A high-quality digital sound, in fact, is not what FFT used. They used pretty low quality (22040Hz) recordings, pumped them through a very heavy (but controllable) reverb, and obviously had very talented musicians write music for that system. While I can't provide the 3rd element, over that month I found free alternatives to the first ~100 of the nearly 200 instruments they used (see: Instruments Wiki), and I began writing code to make use of a software MIDI synthesizer. Sadly, all of this stuff completely lacks the ability to be shown on youtube (some for copyright reasons, mostly for lack of visual nature of music and programming code).

Following the initial investigation, I worked the replacement instruments I found into a replacement table for the purposes of playback and composition. Since I've had the question asked already in-person: "Why does that even matter?" It matters because there are TONS of instruments in the world. If you don't start with just the ones FFT used, it's probably unlikely that you'll use anything like them unless you're skilled at writing music in the style of someone else in the first place. Furthermore, FFT instruments are synthesized, which means you couldn't even hope to find some of them without finding the source material (i.e. reverse-engineering the game) and programming a similar synthesized instrument yourself. So, this is a feature that attempts to offer you a pool of FFT-sounding instruments (without crippling you into only using them) for the purpose of writing songs/music/sound effects that mimic FFT's signature sound (re: low quality audio, massive reverb).

Did you listen to the music I linked yet? As you likely realized, it's all one piece. What changes is the musical theory foundation of: (1) tempo, (2) key (i.e. note like "C"), (3) octave, and (4) scale. These changes have the added benefit of providing an emotional characteristic, like "fear". So, "fear" becomes one configuration for the piece. Meaning, you can ask the engine to play a song like this (i.e. MIDI) in its "fear" configuration. Obviously, you'd have to set this stuff up ahead of time to make sure it sounds good, but the point is that you no longer have to think in terms of music after the initial composition is written; you can think in terms of what it lends itself to emotionally! That's a feature triple-A games have (ex. PSO2), and now so do you -- and it's orchestral-sounding (rather than electronic)!

Thanks for listening and staying interested in Tethical.


Since I don't want to make another post (information is over on twitter anyway), I rewrote gamepad support to use SDL2 (what Steam's Big Picture uses) since someone wrote a Python wrapper for it.

Alright, here it is (same link): download.

It's not 100%, but I believe it will suit your purposes: (1) combo box drop downs use available space (sometimes less options are shown on purpose, though), (2) no controls overlap, and (3) the "Patch ISO" screens are sizable now. Things I know are still wrong: (1) doesn't handle big fonts, (2) controls near edges of parents sometimes get cut off (change to smaller font), and (3) animation tab takes a long time to load (but it looks nice).

Here is a screenshot:

The setting for how many drop down items to show can be overridden easily enough in the code. I'll start working on the rest of the layouts now.

Spam / Re: Purses as weapons
« on: July 17, 2014, 05:07:59 AM »
Little Ol' Lady, Lv. 99
Master Bag Lady (Lv. 8)

  • Accumulate Sweets
  • Squint
  • Pinch
  • Head Shake

  • Ignore Speed Limit
  • Equip EZ-Reacher
  • Cooking +3
  • Kitsch +5
  • Thrift

Okay, then please check the "Items" tab for me of this version: download. It takes a lot of work to reorganize the layout into this format, but, if that tab is laid out how you expect (undo any changes you've done to the XP theme), I don't mind doing it for the rest of them. This version also benefits from the whole form's size, meaning you can see more options at any given time. Again, the "Items" tab is the only one I've done it for, and that took over an hour.

This is what it looks like:

The goal of the version I reconfigured wasn't to let you use the font you had (i.e. the problem font). The goal was to let you set Tahoma (i.e. the font it was designed for) in the theme so that it will look like it was designed to look. There are two problems: (1) the font and (2) the button size XP's button skins add to the really small, nearly absolutely positioned numeric up/down controls. The first issue causes overlaps like the "Effect:" over the combo box; this is the font's fault (i.e. temporarily switch to Tahoma in the theme). The second issue causes overlaps like when the numeric up/down controls would overlap each other (i.e. you could turn the theme to classic in XP which doesn't have those huge button skins, but the version I reconfigured turns that off just for the application).

This Version

Here's a version of that program that doesn't turn visual styles on: download. There were also a couple of other things that weren't configured to have the font changed (the Patch ISO windows, for instance; also, the item heights of the ENTD unit list). This addresses those. As per the previous post, it looks for the font you set in the theme under "Message Box" (whereas the previous version didn't). The visual styles are turned off to prevent the blue buttons (which are large) from winding up on the numeric up/down controls.


  • Open FFTPatcher to the window you're having trouble with.
  • Right-click somewhere empty on the desktop.
  • Select "Properties" from the context menu.
  • Select the "Appearance" tab.
  • Click the "Advanced" button.
  • Choose a different font and size until the program looks like you want it to (hit "OK" then "Apply"; NOTE: the program probably expects Tahoma 8pt).
  • Optional: Change the font back afterwards.

The font is wide (i.e. change it in the theme to one that's less wide with less vertical spacing).

Hacking / Re: Waveform/Instrument Injection
« on: July 06, 2014, 01:53:03 AM »
Something else maybe worth looking at is that PSound finds 2 really short audio files in BATTLE.BIN. I found them at 0x2d4e0-0x2d760 (185568-186208) and 0x2eaa7-0x2eca6 (191143-191654). Might be an easy target for a quick customization. I think the first one might be the gil award plink (it's 0.05s). I don't know what the second one is, but it's 0.04s.

Hacking / Waveform/Instrument Injection
« on: July 04, 2014, 06:35:12 AM »
New instruments in FFT!


Have not decoded the actual definitions for instruments yet. Have managed to replace the wave data (WAVESET.WD) that they operate on.

Involved files:
  • WAVESET.WD (wave data)
  • The ISO it's on.

  • Drag WAVESET.WD into the PSound program.
  • PSound will show 85 waves (0..84).
  • Pick the sound you want to replace.
  • Export the sound (after configuring PSound to not add extra lead out).
  • Document how long the sound is for reference in picking a replacement .WAV file (NOTE: .WAV file should be 22050Hz, 16-bit PCM).
  • Open WAVESET.WD in a hex editor.
  • The first waveform in that file is at 0x0b40; you can identify waves after this point in the file by a sequence of 16 or more consecutive empty bytes; the data streams start as soon as the first non-zero 2-byte set is encountered (like 0x00 0x02 or 0x05 0x02).
  • Jump to the waveform you want to replace.
  • Determine the length to the next set of 16 empty bytes from the start of the data set. This number is the length in bytes of the data streams in the waveform.
  • Use the following program I wrote to encode your wave file like: python WaveFileName.wav LengthInBytes
  • There is now a file containing the data: WaveFileName.wav.bytes
  • In a hex editor that supports paste overwrite (re: the HxD program), paste over the existing data streams back in the WAVESET.WD file.
  • Clear PSound's playlist, and reload the file by dragging it into the playlist area.
  • If you copied the data over correctly, you'll hear the new wave. If not, you'll hear a stock, choppy wave that PSound plays when it can't decode the data (you can just think of it as an error beep).
  • When you're happy with it, you'll need to replace the WAVESET.WD file in the ISO.
  • To do this part manually, open your ISO in a hex editor, and search for the text string: dwdsP (or the hex string 64776473502016CE). This is the start of the WAVESET.WD file in the ISO.
  • Locate the wave you want to replace after that point.
  • Waveforms contain an unbroken line of 2-byte commands that you can see clearly in a standard 16-byte view (re: look for the column of 0x02, 0x06, or 0x03 bytes). Highlight the data stream until you encounter non-file data (i.e. where there would be a two byte command like 0x00 0x02 there is instead a FE FF). Record this value as the initial write for the file.
  • Now, continue highlighting all the way down to just before the next set of consecutive 16 empty bytes (0x03 in the second command byte signals the last stream of the waveform). Copy this data into an ANSI text file (like 0010.txt), removing the spaces between bytes with a replace all tool.
  • Now, re-encode the replacement WAV file against the ISO's data, like: python WaveFileName.wav LengthInBytes TextFileWithBytesFromISO.txt InitialWriteAsNumberOrHexadcimal
  • The content of the resulting .bytes file can be copied over the data stream in the ISO in the same way as the file (paste write).
  • Your ISO now contains a different sound than FFT shipped with.

Usage (for the test in the video on a Japanese ISO of FFT).
Code: (Command Line) [Select]
python C1.wav 6816 C1.txt 0x360
python C2.wav 3808 C2.txt 0xb0
python C3.wav 3936 C3.txt 0x1c0
python C4.wav 1472 C4.txt 0x250
python C5.wav 3104 C5.txt 0x480
NOTE: Requires installing Python and several dependencies: numpy and scipy.

Code: (Python) [Select]
import numpy as np
from itertools import product
from import read

# Pass through values that line up with offsets: 0x0 to 0xf.
acceptedValues = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, -1.0, -0.875, -0.75, -0.625, -0.5, -0.375, -0.25, -0.125]
acceptedValuesMaxArray = np.array([0.875, -1, ])
allValueRange = np.array(acceptedValues)
# SYNONYMS: 0x06 and 0x03. 0x06 may be some kind of off switch to something 0x02 can do in effects. 0x03 signals the last block follows. They don't do anything special to the data, though.
amplitudeCommands = [0x02, ]
# Cutoff seemed like < 0x5d. Also, cannot use anything evenly divisible by any in range: (0xd, 0xe, 0xf). However, everything above the first 16 (with the exception of the 0x5x block, which is a pass through exactly? the same as 00) are effects, and can safely be ignored for the purposes of writing pre-amplified data into the waveform.
exponents = [i for i in range(0, 0x10) if (i == 0) or ((i % 0xd) > 0) and ((i % 0xe) > 0) and ((i% 0xf) > 0)]
negativePowersOfTwo = list(product(amplitudeCommands, exponents))

# Yield successive n-sized chunks from l. Used to slice bytes of an incoming wave into 28-sample sets (encodes to 14 bytes).
def chunks(l, n):
for i in xrange(0, len(l), n):
yield l[i:i+n]

# Convert sample value (expects 16-bit signed integer) into a value from -1 to 1.
def getSampleValue(n):
thisSampleValue = np.nan_to_num(n) / 32767.0
return thisSampleValue

# Rounds actual data to data represented in the encoding scheme.
def roundToNearestAcceptedValue(sampleValue, valueRange = None):
valueRange = valueRange if valueRange is not None else allValueRange
delta = None
actualNumber = None
for possibility in valueRange:
thisDelta = abs(sampleValue - possibility)
if (delta is None) or (thisDelta < delta):
delta = thisDelta
actualNumber = possibility
return actualNumber

# For values of 0x0 to 0xc in command 0x02, yield: 2**(-n). Values in 0x1x range are a concave falloff. Values in 0x2x range are a convex falloff. Values in 0x3x range are a whole sine wave. Values in 0x4x range are the first 4/5th's of a sine wave.
def getModifier(value):
return 1 / float(2 ** value)

# Get the closest amplitude modifier in the encoding scheme. Intended for use with maximum values.
def getClosestModifier(value, valueRange = acceptedValuesMaxArray, negativePowersOfTwo = negativePowersOfTwo):
# If the value is not zero, go looking for it as a max/min value in the sliding table of values.
if value != 0:
delta = None
actualNumber = None
actualModifier = None
for idx, (command, power) in enumerate(negativePowersOfTwo):
# Typically, get the value of: 1 / 2**power.
modifier = getModifier(power)
# See if any of the maximum values are now equivalent to the supplied value.
for possibility in (valueRange * modifier):
thisDelta = abs(value - possibility)
# If this value is closer than previous values, store it as new solution to best-fit question.
if (delta is None) or (thisDelta < delta):
# Try to escape early. The delta is an exact match.
if thisDelta == 0:
return actualModifier
# Otherwise, store best and continue.
delta = thisDelta
actualNumber = possibility
actualModifier = idx
return actualModifier
# If the value is zero, it can be represented in the pass through, which will be data set (2, 0) at index 0 of negativePowersOfTwo.
return 0

# Translate the 28-sample set into a 16-byte data stream of form: AACC 00112233445566778899AABBCCDD
def getBytesForStream(dataStream):
samples = np.array([getSampleValue(rawValue) for rawValue in dataStream])
maximumValue = samples[abs(samples).argmax()] #max([abs(sample) for sample in samples])
# Store bytes for wave amplitude modifier and stream.
modifierBytes = [0x0, 0x2]
bytes = []
# If the maximum value is not in the default max values list, look it up. Majority case.
modifierIndex = getClosestModifier(maximumValue)
command, power = negativePowersOfTwo[modifierIndex]
thisModifier = getModifier(power)
modifierBytes = [power, command]
scaledDefaultValues = allValueRange * thisModifier
roundedValues = [roundToNearestAcceptedValue(sampleValue, valueRange = scaledDefaultValues) for sampleValue in samples]
# Find indices of values in list.
scaledDefaultValues = list(scaledDefaultValues)
indices = [scaledDefaultValues.index(roundedValue) for roundedValue in roundedValues]
# Get (1, 2), (3, 4), ... (n, n + 1).
groupedIndices = [(indices[i], indices[i+1]) for i in range(0, len(indices), 2)]
# Write the bytes out.
bytes = [] + modifierBytes
for start, finish in groupedIndices:
# Calculate the 2-dimensional array offset in hex of the sliding table values.
x = start * (16 ** 0) + finish * (16 ** 1)
return bytes

# Process all the data of the incoming wave.
def processData(data, samplesPerByte = 2, waveFormBytesPerStream = 14, limit = None):
# Typically: 2 compression modulation bytes followed by compressing 28 bytes into 14 bytes such that 1 byte equals 2 samples. Total: 16 bytes per stream.
fourteenByteDataStreams = chunks(data, waveFormBytesPerStream * samplesPerByte)
# Store return data in string (intended for pasting in a hex editor).
result = ""
totalBytes = 0
# For each stream, bet the bytes.
for dataStream in fourteenByteDataStreams:
theseBytes = getBytesForStream(dataStream)
count = len(theseBytes)
# If this is the last stream to be written, signal with 0x03 instead of 0x02 (or 0x06). Then quit.
if (limit is not None) and (totalBytes + count) >= limit:
theseBytes = theseBytes[0:limit - totalBytes]
theseBytes[1] = 0x03
result += "".join(["%02X" % byte for byte in theseBytes])
totalBytes += len(theseBytes)
# Otherwise, add in form of AACC00112233445566778899AABBCCDD.
result += "".join(["%02X" % byte for byte in theseBytes])
totalBytes += len(theseBytes)
return result

# For arguments, accept: 37 (or) 0x25, 0x800 (or) 2048, etc.
def hexOrInteger(inputString):
return int(inputString)
except ValueError:
return int(inputString, 16)
return 0

# Usage: python WaveFile.wav
# Crossed Streams Usage (short): python WaveFile.wav OtherStream.txt InitialWriteFor
# Crossed Streams Usage: python WaveFile.wav OtherStream.txt InitialWriteFor OtherStreamWriteFor ThisStreamWriteFor
if __name__ == "__main__":
import sys
# Arguments: No input file.
if len(sys.argv) == 1:
print "No input file. Usage: python %s WaveFile.wav\nCross Stream Usage: python %s WaveFile.wav OtherStream.txt InitialWriteFor OtherStreamWriteFor ThisStreamWriteFor\nNOTE: ANSI files only." % (sys.argv[0], sys.argv[0])
# Arguments: No length.
if len(sys.argv) == 2:
# Turn length into an integer.
sys.argv[2] = hexOrInteger(sys.argv[2])
# Arguments: Cross stream file.
if len(sys.argv) == 3:
# Arguments: Cross stream initial write for.
if len(sys.argv) == 4:
# Turn initial write for into integer.
sys.argv[4] = hexOrInteger(sys.argv[4])
# Arguments: Cross into other stream for.
if len(sys.argv) == 5:
# Turn cross into other stream for into integer.
sys.argv[5] = hexOrInteger(sys.argv[5])
# Arguments: Cross back into this stream for.
if len(sys.argv) == 6:
# Turn cross back into this stream for into integer.
sys.argv[6] = hexOrInteger(sys.argv[6])
# Arguments.
thisFilename, waveFilename, length, fileWithStreamFromISO, initialWriteFor, otherStreamWriteFor, thisStreamWriteFor = sys.argv
# Print back the filename for reference.
print waveFilename
# Read data.
rate, data = read(waveFilename)
# Get the bytes of the file body.
result = processData(data, limit = length)
if fileWithStreamFromISO is not None:
crossedStream = ""
parts = []
currentFileCaret = 0
currentResultCaret = 0
resultLength = len(result)
# Read the other stream.
with open(fileWithStreamFromISO, "r") as f:
stream =
# Initial write (write X bytes of the result).
count = initialWriteFor * 2
currentFileCaret += count
currentResultCaret += count
# Enter into a loop of crossing back and forth between the other stream and the result stream.
while currentResultCaret < resultLength:
# Write from other stream.
count = otherStreamWriteFor * 2
currentFileCaret += count
# Write from this stream.
if currentResultCaret < resultLength:
count = thisStreamWriteFor * 2
actualEnd = min(resultLength, currentResultCaret + count)
count = (actualEnd - currentResultCaret)
currentFileCaret += count
currentResultCaret += count
crossedStream = "".join(parts)
# Print the byte count of the combined streams.
print "Bytes:", (len(crossedStream) / 2)
# Write the bytes out to a text file (for copying into a hex editor).
with open("%s.bytes" % waveFilename, "w+") as f:
# Print the byte count of the result.
print "Bytes:", (len(result) / 2)
# Write the bytes out to a text file (for copying into a hex editor).
with open("%s.bytes" % waveFilename, "w+") as f:

Hacking / Re: SMD Parser (WIP)
« on: June 27, 2014, 10:00:02 AM »
Let the most bizarre game of "Name That Instrument" begin: Instruments.


Disgaea's "Red Moon" (as found on VGMusic)

Instruments 41 and 42 (main, accompaniment).


I have discovered what offset 0x1A-0x1B (bytes 26 and 27) is (part of the 3rd unknown block on this page: Music/SMD). This sound file demonstrates a kind of reverb for values of 0 (0x0 0x0), 1084 (0x02 0x1e), and 15364 (0x04 0x3c; what FFT SMDs have): listen.


I'm sure it's been explained elsewhere about the SMD format, but most of the stuff is not complicated (considering they're mostly just MIDI files, which is a mature specification even back in 1997).

To help visualize the songs, I've added the feature to plot the notes and instruments out (because I'm having trouble finding suitable alternatives for the samples FFT used). If you can understand something like the graphs, I can probably set it up to interactively change the note (because the graphing application already supports interactivity). However, that won't cover any of the effects (and MIDI files depend on them to make engaging music).

The following are note graphs for two songs (songs provided).

LvUp L (i.e. "MUSIC_24.SMD") (listen)

KUMA BALL (i.e. "MUSIC_25.SMD", Mr. Bear Goes to the Ball) (listen)
Bass line only.

View: larger.

Hacking / SMD Parser (WIP)
« on: June 25, 2014, 06:41:21 PM »
I know there's already something that will get a MIDI into SMD format. I was curious to get the notes out of an SMD, though. This is the file "MUSIC_24.SMD" (LvUp L) with varying MIDI instruments: MUSIC_24.mp3.

As soon as I finish cleaning up the code, I'll post a link here. I believe some of the unknowns point to the information the BGM test shows (an actual title, author, and help text), but I wasn't that curious.

Tethical / Re: Tethical Channel Trailer
« on: April 20, 2014, 05:34:07 AM »
You mean the stuff they tweet?

Code: [Select]
Why is there a mic?

@gordonramseypage Hell if I know. #rampage?

@gordonramseypage Wer hat dich denn aus dem Käfig herausgelassen? ("Who let you out of your cage?")

@gordonramseypage Моя хата скраю #тихо ("It's not my business"; idiom; #quiet)

@montajeRequerido (assembly required)
@gordonramseypage Él que tiene boca se equivoca. ("We all make mistakes"; idiom)
(Don't care; idiom, "I don't have a camel in the caravan.") @gordonramseypage ليس لي فيها نقة ولا جمل
lam-yeh-seen lam-yeh feh-yeh-heh-alef noon-qaf'teh_marbuta(heh) waw-lam-alef jeem-meem-lam

@gordonramseypage 知らないwwwww ("I don't know, lol.")

Tethical / Re: Installation instructions
« on: April 20, 2014, 12:57:39 AM »
I guess you can consider it bleak. But, the actual project is:
  • About 90% done;
  • Can already target Windows, Linux, and Mac (because of Panda3d);
  • Can be run in a web browser (because of Panda3d);
  • Has a tool to create quality 2d effects;
  • Has a tool to create quality bitmap fonts;
  • Has the ability to display any language (multi-language support), including non-spoken (like Alchemy) and dead languages;
  • Has a tool to easily recolor assets, including while the game is running;
  • Has a tool to create mechanic functions via drag-and-drop;
  • Has a tool to visually preview mechanic functions, including a visual representation of what kind of number to expect out of it;
  • Has a tool to visually preview and edit map tiles;
  • Has a tool to visually preview and edit targeting functions;
  • Has a tool to visually preview and music files, including their tags;
  • Has a tool to visually preview and edit items;
  • Has a tool to visually preview and edit conversations;
  • Has a tool to add and edit races, genders, and names;
  • Has a tool to add and edit skills; and,
  • Has a double-click to test event feature.

I always wonder how a word like "bleak" can be brought up in the face of Kivutar's year(s) of work and my three years of work on this project. I mean, there are videos clearly showing what it's capable of, right? Programming isn't something that necessarily needs to change over time. Once it's done, it's done. There's just a ton of stuff to do as relates to an sRPG, and I've done most of it, which means all you'd have to do to use my work is configure the engine the way you want to use it (and provide content). That means you've got something like 110,000 lines of code at your disposal when you use the engine. When you use the Sprite Animator to create content, that's 32,000 lines. The Font Tool is 43,000 lines. The Sprite Remixer is 15,500 lines. That's 200,500 lines of programming you don't have to do. This being an engine (rather than a game), isn't that the goal -- to not have to write code? Is that outcome bleak?

Tethical / Re: Installation instructions
« on: April 19, 2014, 08:36:31 AM »
Yes, that was my plan. The current plan is cutting that to 1/10th of what I wanted to accomplish, aiming for just $2000, but also providing a playable tech demo related to sRPGs (working on this now), open access for the Kickstarter campaign month to the three tools I've written (the Sprite Animator, Unicode Font Tool, and the Sprite Remixer), a playable demo related to card games (done), and a youtube channel filled with videos that introduce or further explain the claims I make about what the engine can already do (mostly done; Assuming that goal is even reached, more things from the original plan will be incorporated as stretch goals are reached. I'm taking longer to do the planning than I originally said I would because I don't want to have any regrets about this next campaign. If it's not successful, I have to walk away from the project and return myself to the job market.

Tethical / Re: Installation instructions
« on: April 19, 2014, 01:13:34 AM »
The IRC thing and the online demo (which requires running the server as a web application) was something Kivutar was offering back in 2012. He's still tangentially involved in the project, but I think the general lack of interest in such an IRC channel and the online demo may have contributed to his decision not to maintain it. This website (FFH), as far as I understand, is available in part because of him, though, and I've been developing that code since then. There will be a playable tech demo soon, but it will be standalone (rather than something played online).

Tethical / Re: Installation instructions
« on: April 18, 2014, 04:30:12 PM »
That .p3d file is just the files located here wrapped up into a bundle:

You'll need the Panda3d Software Development Kit (SDK) and Python 2.7 (though Panda3d's SDK comes with a pre-configured python shell called ppython.exe). That can be found here: Python 2.7 can be found here:

The two files you'd want to run (i.e. double-click) are located at /server/ and /client/

Note that you may need to make a file like "panda3d.pth" in the Python27 installation folder (or you can put it in /Python27/Lib/site-packages) for Python to find it:
Code: (pth file) [Select]


Tethical / Tethical Channel Trailer
« on: April 13, 2014, 11:44:07 PM »
Channel Trailer

Switch to high-definition to see how it looked on my screen.



First, I want to thank everybody who's contributed sprites to this website over the years; this video would have been a lot harder without you. In many ways, this is a culmination of my own efforts, too. While, yes, they've been used to super-impose Twitter into an sRPG context, at least that can be done in a straightforward manner now. Earlier in the development of this engine, we were suggesting that you just replace whatever character you want with a special symbol. That means you might have typed "A" for the Twitter logo to show up. Now, you can just type an appropriate Unicode symbol, like the "Bird" (U+1F426; 128038) in "Miscellaneous Symbols and Pictographs" (U+1F300 - U+1F5FF). You can also properly comply with Twitter's somewhat meticulous guidelines for using their logo, too. That would have been a nightmare before when one font took a whole day to make! Now, the Unicode Font Tool can spit out huge fonts with a variety of colors and variants without too much effort from a user.

And the styles available might even turn out really good-looking, too!

And, for that rare occasion where I decided to actually paint on a sprite:

Thanks for watching!

Spriting / Re: Choto's maybe sprites
« on: April 09, 2014, 01:21:04 AM »
Those arms are pretty damn convincing. I feel like maybe the left arm is swinging out when it should be swinging in on its farthest back frame. I know you mentioned flashing; that left hand looks disconnected when it's behind the body. I think everybody who knows who Umaro is would recognize it immediately.

Pages: [1] 2 3 ... 24