My Family and Other Fish (PerlayStation Part 2)

Faced with any problem, there are many potential approaches. This, I have realised, is amply illustrated by the members of my own family, further reinforcing the educational value of having one. I shall anonymise them for my own protection, and as a disclaimer also state that everything I say about them or anything at all is probably wrong. In fact I have already issued my daily, pre-emptive, unspecified apology to my wife. For me, game coding in Perl is no different.

Identify Problem

Take the aforementioned Mrs S, for example. Faced with a mildly unacceptable state of affairs, her approach is reliably consistent. A detailed root-cause-analysis invariably identifies the source of disquiet: it often comes down to something I did, occasionally something I didn't do, and on serious situations something I was possibly thinking of doing. Her problem can be retrospectively solved if only she had picked any of the better looking and supremely solvent alternatives available to her. My fault then, for choosing the terminal to program Perl Games in. This “blame someone” approach never solved anything, but in difficult situations diverts attention, explains failure and justifies expenditure on jewellery, home decorations, the plumber, or in the case of software development, discarding previous knowledge and using a more popular, fancier, methodology like the neighbours.

Consider Ignoring It

My rather chilled-out older daughter on the other hand handles difficult problems with eminent ease. Her energy-efficient solution is simply to ignore them, saving her time, expense and effort. "Dad, it is only your problem if you see it as your problem." In reality, many problems have always existed; they are not created de novo. They don't have to be your problem, and the world will keep turning, and you will find ways of doing without. Who needs your games? Why do you do open source? Why in fact, do anything strenuous at all, one might say. Perl was never a powerhouse gaming tool, and terminal is not where one looks for arcade thrills given technologies offered by graphical tool-kits and modern browser engines. But one makes games for many reasons. In making games you discover how things work, you learn strategies, transferable skills, and who knows, maybe give fun to others. Critically you develop tools that allow you to make games and practical utilities easier. Indeed, game coding is a diversion, not the end-game for me. The tools one creates to help game development may also help in other projects.

Unexpected Benefits

I do have another hare-brained offspring, a delightfully positive and more energetic individual whose attention is devoted to exclusively herself and her friends. There is seemingly nothing she can not solve by merely fluttering her eyelids and exuding praise, and at the same time getting a profitable outcome. “Oh daddy, those socks go so well with your sandals, but I have nothing to wear for the par… study-session this evening, can you please buy me a <insert-any-item that-could-not-conceivably-improve-grades>, PLEASE???". In reality coding without feedback, whether positive or negative, is difficult. One needs motivation, a second pair of eyes to affirm or maybe redirect thoughts, and recognise connections that may not at first glance be apparent, and that motivation is by definition outward looking. Certainly that motivation factor may be driving secondary gains for other people, but that by no means diminishes its value. Who knew that roller skates actually help effective group-learning?

So the resultant path that Term::Graille has taken is this. It avoids the fancier toolkits that rely on libcurses or libtickit. It starts off as a graphical tool for a non-graphical interface. For practical applications it emulates real-time interactivity (instead of using things like libev) for an environment that is principally asynchronous using Term::Graille::Interact. This is inevitably weak and has to be to be stressed to to become optimised, and game development perhaps allows this stress, highlighting failures in other existing code. Just developing one game is a dead end, however and the diverse set of problems one might face requires more specialised assets. Term::Graille::Sprite, like my daughter’s roller skates, does not outwardly have any of the features that will be required for serious, useful applications. But who knows, it might reasonably stress the platform and may offer secondary entertainment for others.

Term::Graille::Sprite

So what is a $sprite? A Term::Graille::Sprite object which can have a {shape} , a {pos}ition on a screen, and a {vel}ocity. {vel}olicity is a matter of displacement over time, and Term::Graille::Interact, the time is represented by the refresh cycles for the keyboard read routine. The updating of the sprites may be prolonged by skipping a number of updating events. Motion is simulated by blank->()ing a sprite current position and re-blitting the image on the screen. It may interact with other sprites, e.g. collide->($another_sprite) or the environment e.g. edge() or with the user (via an addAction() on Term::Graille::Interact. We may have multiple sprites and these can be handled as a group of sprites, and a SpriteBank object is also provided, that keeps a store of these groups of items, updating them automatically each cycle as needed, or removing them if set to be {destroyed}.

my $spriteBank=Term::Graille::SpriteBank->new(); # store sprites
my $dir="./sprites/";   # path for predefined sprite shapes
my $bat=new Term::Graille::Sprite(data=>[[("█") x 6]],pos=>[20,0],
   bounds=>[1,14,60,0]);   # creating a bat
my $ball=new Term::Graille::Sprite(pos=>[20,3],vel=>[1,1],
   bounds=>[1,14,70,-1],skip=>6);    #  default shape is ⬤ 
$spriteBank->addSprite("player",$bat);  #  Adding $bat to  spriteBank
$spriteBank->addSprite("ball",$ball);    #  Adding a ball

One imagines in the future, one would include animations, physics (e.g. mass, acceleration and gravity). But what is clear is that in developing games, we find multiple failures in Term::Graille. Glitches as the drawing application plots off screen or experiences an error in data supplied. These should be cleanly handled, and one gradually makes adjustments for this, all the time hoping that these changes don’t break previous applications. Breakout is a prototype game that uses Sprite.pm

Inconclusion

My goldfish, Goldzilla, on the other hand has a much wiser outlook to my life’s difficulties. She recognises my flaws and chooses to ignore them. She appreciates my problems, sympathises, listens calmly to my rants, but only ever offers advice when asked. She never showers me with praise to get a new aquarium ornament and appears to mouth out Perl code to herself, if only I could hear this stream of wisdom. Here is the mainstay of problem solving. You are either provided with the tools to solve them or you make the tools yourself. The majority of useful tips will remain unheard, but they do exist and you have to listen closely…and use your imagination.

Done before, Done better, Done again differently.

A Fool's Errand, and Quantum Theory

It is my firm belief that every thought or idea that you or I have, has been had before. On the balance of statistics, the chances are that those that had these ideas handled it better, and have developed more powerful utilities to exploit these innovations. One therefore has a few possible options, when thinking of creating a solution to a problem. The first probably is to look for other published solutions and use them; these may be more mature, tried, tested and optimised. The second is to go ahead and implement another idea, foolishly perceived as an innovation, leading to a proliferation of methods duplicating, triplicating existing work, in the end producing a half-baked distraction.

Statistics indicate that someone will take that path of the fool. I am not going to argue with Quantum Programmodynamics; if it has to be someone, let it be me. Interaction in console applications may involve the ping-pong between a script and STDIN. It may be more sophisticated using Curses::UI. This is established, used for heavyweight applications and has a superb feature set. It could be more modern using Tickit by Perl's resident genius and author of over 235 Perl modules, Paul Evans; powerful, versatile, event-aware and handled in a Perlish way, Tickit is the API for the future of Perl console applications. Or one could try and invent something different. Not better, not more powerful, not more elegant. Just different. Why? Quantum, that's why.

There may be reasons other than pure bloody mindedness or foolishness for doing something differently. Indeed, perhaps the only way to learn to appreciate the right way, is to do the wrong thing. Honestly.

Interactive Applications with Term::Graille

Term::Graille offers pseudo-pixel graphics to the standard ANSI console, now is acquiring interaction tools. Interaction is handled primarily by the Term::Graille::Interact tries to to remain as "Pure Perl" as possible, and minimise reliance on external libraries. Interaction is via a keyboard, and thus uses Term::ReadKey. Rather than using libev/EVent, it relies on querying the keyboard every so often (default every 50 milliseconds) and dispatches predefined actions depending on the result...a rather old-fashioned way of doing things

One adds key-triggered actions, using addAction(), for each key of interest, passing it a subroutine reference and a description. One can also add various widget objects which temporarily override these actions when they are active using addObject(). There may be actions that occur when without a key press. These can also be added using updateAction().

The best way to demonstrate this is through game development. Term:: Graille's graphical capabilities combined with interaction equals a simple gaming platform. Games may need Sprites, and a Sprite Maker application can also demonstrate interacting capabilities. A glimpse of an early version of such an application was seen in a previous blog post, and discussed in more detail later.

Invading My Space

One simple game is Space Invaders. Shapes are loaded. Sprites are created with shape, location and velocity, and stored in an array. Some move by themselves, others move on user key-presses, others are generated, do their thing and vanish. Our defender's motion uses arrow keys. The aliens and the rockets move autonomously and the graille canvas is updated at regular intervals. (Fonts, Sound and collision detection can be subject of later scrutiny).

One creates an interaction object, adds actions addAction() triggered either by a key, or spontaneously every cycle (updateAction()), and then gets it running.

my $io=Term::Graille::Interact->new(); # a new Interact Object
$io->{debugCursor}=[22,45];            # output for debugging

$io->addAction(undef,"[D",{note=>"Move Left ",proc=>sub{
$defender->{x}=$defender->{x}>=1?$defender->{x}-1:1 }} );

$io->addAction(undef,"[C",{note=>"Move Right ",proc=>sub{
$defender->{x}=$defender->{x}<=65?$defender->{x}+1:65 }} );

$io->addAction(undef,"[A",{note=>"Fire      ",     proc=>sub{
push @missiles,{sprite=>"patriot",x=>$defender->{x}+4,y=>1,dy=>1};
$beep->playSound(undef,"A#1");}}  );

$io->addAction(undef,"p",{note=>"PAUSE ",     proc=>sub{
    $stopUpdates=$stopUpdates?0:1;}}    );

$io->updateAction(\&update);  # this action is executed every read key cycle
$io->run();              # this starts the interaction.

This can yields the interaction component of a simple test 1st game for the PerlayStation Terminal Games Console. There is prior art, of course: these are better than mine. Here is one by a Perl Monk called domm who also did a version using SDL and one in Tk by CECALA

invaders.gif

PerlayStation Games Console (Part 1)

Itchy fingers

A few reddit posts ago I saw an interesting article about maze generation and game written in Perl. Game development, I fully believe, is key to intellectual engagement, provides amusement to developers and non developers, and highlights the capabilities of a programming language. This led to an brief exploration of other Perl arcade/action games; Such games such as construdo and deliantra show how complex games can be created. Frozen Bubble is another addictive Perl classic. As a non-developer, I find these games only demonstrate the chasm between my lack of coding agility and the cleverness of others.

It's been done before

SDL and OpenGL seem like a way to go. A useful list of gaming libraries are provided by Debian Games Perl development packages and deliantra are examples of what can be achieved. Some interesting frameworks Quest3 are available although many with no recent updates e.g. this one.

But old dogs like me can't learn new tricks (or even old tricks for that matter), I figured the easy way to bridge this chasm between my capability / capacity to learn and that required to produce a respectable output requires a new framework. I hear groans all around, but wait, don't touch that dial,...imagine a framework that is simple enough for the newcomer or old timer, complex enough for a respectable game production, and accessible enough to be installed without needing a snowstorm of dependencies. Big ask? To have arcade games with moving sprites, collision detection, gravity, scrolling shooters, platformers, RPGs, and yes all these written in Pure Perl? Easily? Without being familiar with complex external libraries? Well I tried...I tried using GUIDeFATE ( a GUI designer) drawing sprites in SVG...it is clearly possible...but certainly not accessible.

Animations

Most people will have some difficulty installing GUIDeFATE (its current iteration on CPAN is near end-of-life, due shortly to be overhauled into version 0.15). Furthermore, I feel firstly that there are several components that I have yet to learn, including event handling, user interactions, etc. Secondly, for the code that is generated to useful and easily used in producing different games it needs to be consistent, and abstract out the complexities of the graphical and user interactions and thirdly that I will need a significant amount of third party help.

Consolation games

So, a radical step backwards, and look at game development as an abstractable process, with functions that can be extended to any interface/backend etc. Let's make console games that look like arcade games...a Perl games console, with games running in a console (i.e. a terminal window). Terminal games do exist, and some are even written in Perl, but the majority are made using "single use" code, i.e code that one cant borrow to develop one's own ideas easily.

Term::Graille is a step in that direction. You will have encountered it in one of my previous blogs. As a platform it includes pseudo-pixel graphics, with multiple graphical operations, and an Interaction module with Menus, Dialog boxes, Selectors etc. Later it will feature an Audio/Speech module, and Sprites. As a system its goals will be to have minimal dependencies, and key will be simplicity. Initial applications will be simpler tools that will enable game development that follows...text editors, sprite generators, graphics. All of these delivered through familiar, intuitive interactions, but all on the terminal window.

Spoken like a 1980s chip

In the beginning

In the beginning there was light. Of course there was, but a bang must have followed shortly after. It is not unexpected that the communication between organisms, surrounded by a fluid whether it is air or water, is primarily acoustic rather than visual. While vision remains the king of senses and chemical signals are ubiquitous, interaction using a oscillating pressure producer and a corresponding sensor remains the best compromise to create a versatile rich, abstracted, linear data transfer not requiring line of sight. or any other complex infrastructure apart from a medium that envelops the organism. Thus, speech. I recall the early days of my youth my ZXSpectrum had a Currah Microspeech module which, with only a 2K ROM, was able to produce an infinite number of raspy, but mostly recognisable words. Flash-forwards to today, we have far more powerful utilities producing sounds almost indistinguishable from another human. and Perl allows access to these speech engines. These are powerful, non-trivial utilities, with superior abilities to change intonnation, speed and other forms of expressive audio manipulations. For those interested polease explore PerlSpeak, Festival, e-Speak. Perl is certainly not short of vocalising options.

Pure Perl Implementation

As an old simpleton, however, I can not drag myself away from the genius of the guys who with such limited resources managed so much, into the modern world were memory and processor power limitations are of no real issue. The SP0256-AL2 is the centre of this remarkable primitive utility, and I took it myself to explore how this worked, to transform it into a simple module that can be imported into any Perl program, with no dependencies apart from a means to transfer data to a speaker. There indeed many attempts to emulate this little chip, though I have not come across any that specifically use Perl, I do find resources including this one from Greg Kennedy that allow translation to the allophones used here.

Re-inventing the wheel?

Why do things again that far cleverer people have already done, with far more advanced methods? For several reasons. It helps me learn how things are done. Old methods are not going to be as good as new ones, but use far fewer resources, and this would allow quite a lightweight model for speech synthesis that could be embedded in simple applications and games. This would not require any installation of any heavy weight back-ends, polluting the system with more and more infrequently used libraries. So the "plan" is 1) produce a stand-alone speech synthesis module, 2) progressively make the module more accurate and more recognisable 3) eventually have something anyone can use for fun or for real-life needs.

Now I did make a Piano-like monophonic player (Enable the sound in the embedded video sample to hear), based on a memory of a similar utility I saw many years ago. Most web examples use /dev/dsp for audio transfer to the output device, but this virtual interface no longer exists. A pipe to padsp does allow the emulation of /dev/dsp, and this is what I have used for Linux OS; Win32::Sound has a Windows equivalent of a sink for the raw audio data, as yet to be figured out. Thus we have a beginning of a module:-

SP0256.webm

Emulation

The classic method for emulation of this chip appears (as far as I can tell) to be to record the sounds output from the chip, sampling at much higher frequencies than is output (effectively adding a high pass filter). This results in errors and distortions. Such converted data is available as WAV files, and do not have any of the analog filtering that is performed on the original chip, this is actually much lower in quality that the original. But borrowing this data from various sources enables some semblance of a speech synthesiser, and my experimental modulino represents an early attempt at using unprocessed wave forms. But these wave forms are not only inaccurate and noisy compared to the sounds that came from my 40 year old ZX Spectrum, they take significantly more memory. The unpacked data in a script took 1/2 MB and packed into a Storable file, still take just under 100kb. Can't see my Speccy being too impressed.

Missing the point

BUT this simple way belies the cleverness of the original chip mode of operation. To understand how this is managed in 2kb of ROM one has to explore the disassembly of this ingenious device. Unlike modern speech synthesisers with banks of pre recorded audio allophones, the SP0256 actually appears to have built the output waveform on the fly algorythmically, much the same way as piano.pl generates the raw tone data for each of 96 notes. I do need to pore through this code not that I am familiar with the ancient microprocessor (or assembly for that matter) to see how this actually works. It should be entirely possible to create an ultra-lightweight module capable of generating recognisable speech in Pure Perl without any external speech libraries.

Casting Perls before Splines

As I sit pondering my peas at the dinner table, my thoughts are unnaturally drawn to the similarity between these pulses and Perl. A famous poet once said that "For a hungry man, green peas are more shiny than gleaming pearls". From these green orbs on my plate, the mind drifts to a recent virtual conversation regarding logos, branding, rebirth and innovation in Perl. One wonders whether such heated debates are important, relevant and what it might mean for Perl in the future. The Camel (from the O'Reilly Book on Perl) has long been the image associated with the language, along with the Onion (Origin perhaps from Larry Walls' "state of the onion" presentation). Personally it is not something that I feel passionately about. "Perl, with any other logo would be just as quirky" as Will Shakespeare is reported to have said. But The Camel is the popular, recognisable standard "logo" with some, as yet to be tested, copyright and trademark "issues"

Any way I took it myself to analyse the situation and have finally come to the conclusion that we may be looking at the "problem" the wrong way. Perhaps we are looking at the bigger picture when we should seeing the picture bigger. Maybe, just maybe, that picture of a camel doesn't symbolise Perl, but in fact IS Perl...Perl code, that is. I know it is possible to make pictures that aren't valid perl code. But perhaps over the decades of use we have come to accept an illusion as a reality. When one gives such an illusion a "True" value, one also blurs the distinction between the Virtual Image and a Real Image.. You see a Virtual Image is an image that APPEARS to represent something, but only a Real Image can be projected.

logo.png

So lets examine this image in cruder detail. What immediately pops out to the casual observer, is the silhouette clearly is a two line regular expression:

s/A\
/rl /g

Now why on earth does this snippet appear in the camel in the classic book of Perl? Surely this can not possibly be by chance. Some predestination HAS to be involved. It is at this point, four aforementioned peas slipped off my spoon on to the floor. I don't know if any of the readers who are male and married, have had this experience before, but it was with enormous relief that I saw, glancing up, that this misdemeanor was missed by Mrs Saif.

But surely a sign...the rows of peas...and a regular expression..it can ONLY mean one thing.

$Logo="PEA\n" x 4;   # 4 rows of PEAs
$Logo=~              # Apply the code in the camel
s/A\
/rL /g;
print $Logo;         # print result

#result:- "PErL PErL PErL PErL ";

The rows of "PEA"s get turned into a string of "PErL "s. It seems obvious to me that while we look in vain for the answer to our problems, it is the answer that finds us, the illusive emerging from illusions. A famous admiral said, putting his telescope to his blind eye "I see no ships of the desert". Of course he didn't. He saw Perl code.