Author Archives: Nick

Adding auto-format code indenting to Sublime Text 2

While looking for a way to simplify indenting multiple lines with Sublime Text 2 I came across a useful way to auto-format code indenting (similar to the auto-format function in Processing).

To add the keybinding in Sublime Text, select Key Bindings – User in Preferences. Next, add the following line in between the square brackets.

{ "keys": ["super+t"], "command": "reindent", "args": {"single_line": false} }

Pressing command+t will auto-format your entire document. (I chose command+t to match Processing’s auto-format keybinding, but you can use any keyboard shortcut you like.) You can also change the “single_line” argument to true if you’d just like auto-format to run on your selected lines. Enjoy!

Windows 8: Desktop destroyer? (and not in a good way…)

As a self-professed power user, I’m rooting for Windows 8. I’ve been using Apple computers exclusively for about a decade, but as Apple shifts to focusing on consumer products such as phones and tablets and less on actual computers, I’ve grown disenchanted. Buying a desktop computer in particular from Apple now entails very high prices for outdated hardware. The control that Apple has racheted up over its users through constant disruptive OS updates has had me pining for the good old days: the days where my computer was mine to customize and to use as I please. In that bygone era, a computer could last 5 years or longer through upgrades; nowadays, RAM is soldered onto laptop motherboards or all-in-one iMacs and you’re expected to buy a new machine or a new OS interation every two years. So, despite being chronically disappointed with every iteration of Windows from the last 10 years, I want Windows 8 to be a success. I want it to be a success so I have an alternative.

I know there are others like me. Anyone who does anything professionally with a computer (besides email and word processing) is a part of this group. True, we may not be as large and as attractive a market segment as those targeted by the iPhone and the iPad, but for Microsoft, a company who has seen its mobile phone efforts completely ignored by the mass market, I would have thought we would represent some low-hanging fruit.

Enter Windows 8. Against my better judgement, I’ve let Microsoft’s pleasing new designs convince me that Windows 8 will take me to a desktop computing nirvana. I assumed that Windows 8 would make (or at least strive for) a more powerful, efficient, intuititive desktop computing experience.

But it isn’t. It’s designed primarily for touch screens, and when touch can’t handle the tasks at hands (read: often) it switches back to what feels like an emulated version of Windows 7. It’s a weird mish mash of past and what is presumed to be the future. This makes sense for tablet or a laptop/tablet hybrid, but what about for a traditional laptop or a desktop, where one’s most intensive/serious work is to be done?

I get it. Everyone’s doing touch and PC sales have plummetted. I just don’t don’t think touch (or voice control, for that matter) is right (at least not in its current implementation) for most serious computing tasks, and killing desktop computing seems like an awful big sacrifice for a gamble on touch.

In wanting to be new and edgy, Apple’s competitors are merely playing following the leader. No, touch interfaces are not going to replace the keyboard anytime soon. The keyboard is an efficient, remarkably fast tactile user interface. Why are we so eager to abandon it? Just so we can do our best to emulate what we’ve seen in Minority Report and in the Jetsons?

Igloo Command DELUXE now available!

I’m proud to announce that my newest game, Igloo Command DELUXE is now available for iPhone and iPad in the iTunes App Store! It’s truly the game the original Igloo Command was meant to be and by far my most polished effort to date. It boasts new powerups, new enemies, improved graphics and gameplay and new Game Center achievements! I hope you’ll give it a try, and if you do, please let me know what you think either privately or via iTunes’ ratings and reviews!

 

As has become tradition around these parts, I’m kicking off the launch with a HIGH SCORE contest with a retro gaming Champion’s Pleasure Pak as a reward to the plucky winner! That’s right, to thank you for buying and playing my game, I’m offering a 20th Anniversary Edition Game Boy Micro and a Super Mario Bros. 3 cartridge along with a one-of-a-kind Champion’s T-shirt to the player with the highest score (as verified by Apple Game Center) on November 1st, 2012.

To recap, the Champion’s Pleasure Pak includes:

  • Nintendo 20th Anniversary Game Boy Micro system with charger
  • Super Mario Bros. Advance 4 (Super Mario Bros. 3) cartridge
  • Deluxe Edition ‘World Champion’ T-Shirt celebrating your achievement

Please make sure that you are logged in with Apple Game Center before playing to ensure that your score is recorded! Good luck!

How-To: Build a Hackintosh CustoMac Mini 2011

I recently took it upon myself to try building a ultra-budget Hackintosh HTPC (Home Theater PC), following tonymacx86’s suggested build for the CustoMac Mini 2011.

I’m pleased to say that after a few days of tweaking and futzing, I’m now the proud-owner of a triple-boot (OS X 10.7.4 Lion, Windows 7, Mint Linux) Hackintosh CustoMac Mini 2011! The machine boasts a respectable 6096 Geekbench score and cost ~$380 total.

The process wasn’t as hard as I thought it would be, but it wasn’t as easy as I had hoped, considering that this was a ‘suggested’ build. I thought I’d do a step-by-step run through of my experience here should anyone else be considering building the CustoMac Mini 2011, or a hackintosh in general. Since the instructions I used are available elsewhere on the web, I’ll link to the sources I used and just provide my notes and instructions at the points where I found the existing documentation tricky, ambiguous, missing, or incomplete. I should note that I opted for an optical drive and the H61N motherboard (listed as the ‘alternate’ motherboard).

Here’s the high-level strategy you’ll follow:

  • Part I: Building the physical computer.
  • Part II: Preparing the computer to have OS X installed
  • Part III: Prepare a bootable USB stick with OS X Lion on it + tonymacx86’s utilities
  • Part IV: Install OS X
  • Part VI: Configure MultiBeast to achieve full functionality
  • Part VII (Optional): Install Windows or Linux on another partition

Part I: Building the Computer

Building the computer was pretty straightforward. I’m including my directions here for those without experience building PCs. If you’re just interested in the hackintoshing, skip ahead.

First, I attached our i3 CPU to the motherboard using the directions included with the CPU, and then attached the heat sink on top of the CPU. Although I was expecting to be missing a few screws or cables during the build, strangely enough the thermal paste used to transmit heat between the CPU and the heat sink was the only thing missing from the packaging. Luckily, some was found nearby (pictured) – you should be able to find this at a hardware store.

Attaching the RAM was nothing new, a satisfying click into the slot and I was on my way.

Mounting the motherboard in the case proved to be a trickier affair than I had expected: as you can see, the fit is so tight in the MI-008 case, that the power supply (PSU) actually touches the top of the CPU’s heat sink! I found that I actually had to lift the PSU up as I slid the motherboard underneath just so it would fit. I also read that removing the PSU via the screws on the back of the case and reinstalling it afterward works.

After connecting the power supply to the motherboard, I attached the front-panel USB ports and LED lights to the motherboard using the instructions that came with the motherboard for guidance. Same goes for the HD Audio cable. The AC ’97 cable went unused as per the instructions.

I popped off the front of the case using the four plastic hinges and slid in the hard drive and the optical drive and connected them to the SATA power cables and the two blue SATA ports on the motherboard. Again, the fit is very tight, and after you’re done with the build I’d suggest losing the optical drive if you can spare it (more on that later). Make sure the cables are not interfering with the fan’s operation (see if you can spin the fan with your finger without it bumping into a cable).


Part II: Preparing the computer for OS X

To prepare the computer for OS X, I used these steps described on tonymacx86 and elsewhere on the web. They involved tapping the DEL key during startup to enter the BIOS. In the BIOS, I first updated to the newest version (in my case, it was version ‘F8′) of the BIOS by using the BIOS’ Q-Flash option. It loaded the newer BIOS which I had found on Gigabyte’s website and put on a USB stick (note: the USB stick has to be formatted in FAT, an easy task for OS X’s Disk Utility). Once the BIOS was updated, I set the options I was told to, including HPET to 64-bit mode, SATA mode to AHCI, 384MB of shared Video Ram, and Load Optimized Defaults. I just poked around in each of the menus until I found the relevant option to change. I also changed the boot order to load from USB-HDD first, in preparation for the Lion installation from a USB stick.

Part III: Creating a bootable OS X Lion Installer using UniBeast

Creating our bootable OS X USB stick was super easy and straight forward using tonymacx86’s instructions on this page.

Part IV: Installing OS X

To install OS X, I booted from our new UniBeast USB stick by setting the BIOS to load from USB-HDD first. At the bootloader screen, you can begin typing to set a boot flag. The installer would freeze at the Apple logo unless I typed ‘GraphicsEnabler:No’ before hitting enter.

Once in the OS X installer, I used Disk Utility (accessible through the menus at the top of the screen) to format the hard drive. The key setting here was format the drive as ‘GUID Partition Table’. I created a small partition for a Windows installation later. Return to the installer and install OS X as normal.

Once the install is finished, the computer will restart. Again, you will boot from your USB-HDD as your hard drive can’t boot OS X on it’s own yet. This time, instead of selecting the USB stick, select your OS X hard drive and hit enter. You may or may not have to enter the GraphicsEnabler:No flag.

Part V: Configure MultiBeast to achieve full functionality (starting with the ability to boot up on its own)

WIth any luck, you’re now able to run Lion on your computer by booting from the USB-HDD. If you weren’t able to get this far, you may need to scour the tonymacx86 forums for information on which bootflags you’ll need to use based on where your computer hangs when loading with the -v bootflag (verbose mode). God help you if this is the predicament you find yourself in. (Note: Don’t use the onboard VGA port. tonymacx86 cautions that the VGA port is ‘disabled’ and I think using the VGA port caused me a few hours of wondering why OS X wasn’t loading correctly. Use the DVI port.)

Once in Lion, download MultiBeast from tonymacx86’s website here (Note: you will have to create an account with tonymacx86 and log in, unfortunately.) You can check if your onboard Ethernet port works at this stage. Mine did. If not, ferry it over on a USB stick. Also download the appropriate DSDT file for your motherboard from the first comment on the CustoMac Mini 2011 post. (Again, you will have to log in to have access). They are the .aml files – note which one corresponds to your motherboard. Place both the .aml file and MultiBeast on your desktop. Rename the DSDT file: DSDT.aml. (Note: You may or may not have to do this. I had a really hard time getting my DSDT file to kick in, and the instructions are unclear about renaming the file. I renamed mine and placed them both on the desktop and eventually MultiBeast worked. I do not know if the changes had an effect or not.)

Run MultiBeast. You’ll have to check the appropriate options here. This is where I had the most trouble as there are numerous screenshots floating around tonymacx86 showing different settings. You’ll want to enable each of the settings in these two images, with the audio settings in the second image replacing the audio settings in the first. Once you’ve run MultiBeast, reset your system with your fingers crossed. Hit DEL key during startup to enter BIOS and change your boot order to prioritize your hard drive: we’re going to see if your hackintosh can boot OS X on its own!

Part VI: Update Lion to 10.7.4

With any luck, your computer was able to boot back into Lion without the USB stick. You should check what ports work on your computer at this time. At this stage, my ethernet worked, my USB2 ports worked, but my audio port did not work. (Trying to change sound output volume brought up the speaker logo with the ‘no’ sign across it). I wasn’t able to test the HDMI port.

To update Lion, download the combo update directly from Apple here. (Don’t use Software Update). Run the update but DON’T REBOOT when it tells you to. Instead, open MultiBeast and check the options you had before. Once MultiBeast is complete, click reboot on the installer. (Note: It’s probably possible to do the update right away before you run MultiBeast for the first time, but I didn’t do it that way).

Congratulations! Upon reboot, you should have a ready-to-go Lion 10.7.4 Hackintosh. My machine is able to sleep and wake up, plays audio, accesses ethernet, and has working USB ports.

(Optional) Part VII: Installing Windows 7 or Linux on another partition

If you’d like to install Windows, boot from the Windows 7 DVD by changing your BIOS to prioritize the optical drive. Install to the free partition you created earlier. (Or, using Disk Utility in OS X, you can create a new partition now without reformatting. How cool is that?) Note that once Windows is installed, it will have overwritten your bootloader and will now try to boot Windows every time you start up. To get around this, boot from your USB-HDD UniBeast drive again, choose your OS X installation and run MultiBeast. Only check the ‘Bootloaders: Chimera’ option, and reboot. Now your bootloader is back and you can hit any key during startup to choose between OS X and Windows. Boot Camp eat your heart out!

Some Parting Thoughts

  • To update, remember to download updates directly from apple and apply MultiBeast after the update and before rebooting.
  • Consider Kakewalk, an alternate set of hackintosh tools. I don’t mean to sound ungrateful to the good people at tonymacx86, but if you’re like me, you’ll never want to look at that site again after your hackintosh experience. Information is scattered across numerous blog posts, legacy blog posts, blog post comments, forum posts and forum post comments, many requiring you to sign in to access needed files. The presentation on Kakewalk seems, at first glance, to be much more neatly organized — I can’t speak to how well the software works, but I may try it for my next hackintosh build.
  • You can also use a slightly different procedure using a boot CD (called iBoot) to install Snow Leopard. While I did try this route at one point, I ultimately decided to go with Lion as with the dawn of Mountain Lion, Snow Leopard is beginning to look a little long in the tooth, I suppose.
  • If you have any questions or if you believe I missed a step or some information, please don’t hesitate to leave a comment! I will help to the best of my (limited) ability.

My first XBox 360 Foray –

This semester I was able to return to trying to tackle game programming on the XBox 360. The organic behaviors and physics simulations learned in Dan Shiffman‘s Nature of Code class always screamed “Games! Enemy/AI behaviors!” to me and so I decided to choose a platform that would allow for the same OOP concepts employed by Java/Processing as well as a sensitive, tactile controller and a hefty graphics output. Enter the XBox 360, C# and the XNA framework.

During this project I feel like something finally “clicked” for me regarding object oriented programming. I’ve always understood OOP but never really used its capabilities (effectively, at least) to make my projects more efficient, organized, and expandable. While working on my XBox game (think Choplifter meets Geometry Wars) a magical thing started happening: as my project grew, my code wasn’t growing more bloated and complicated, it was growing leaner and more modular. It was a great feeling.

As an aside, I never thought I would enjoy developing on Windows or in a Microsoft-branded IDE (in this case, Visual Studio 2010 Express) – but I have to conclude that VS2010 Express is everything Eclipse wishes it could be. It highlights potential errors before they happen without trying to incorrectly autocomplete what I’m typing. I’m finding it easy to cover new ground without fear of breaking my code.

Here’s a short video of the game so far. I apologize for the quality but at the late hour of the night I could not devise a better way to capture the video output from my HDMI-enabled XBox 360 – which is pretty sad in this day and age, considering that just a few years ago I’d have a bevy of video equipment that could easily manipulate simple composite or S-Video output. A humorous photo of my workspace and photo-taking rig is included here.

The Ridiculous Documentation Rig

The Ridiculous Documentation Rig: iPhone atop Kleenex and game boxes.

By moving every non-player element (e.g. the background, the enemies, buildings, etc.) by the player’s velocity (should the player be either near the left or right third of the screen), I’m able to create the illusion of a scrolling background and a vast virtual 2D space.

What I’ve built so far is only the beginning: tanks fire homing missiles that use a basic seek behavior to follow the player. More interestingly, the geometric alien foes seek the player while attempting to maintain a distance from each other and (more pressingly) any bullet fired by a player. The result is a skittish yet ever-encroaching and inevitable threat against the player. I had to tweak the weights and the maximum forces applied to the squares quite a bit to get the desired effect. At first, the squares flew far away from the hunt when confronted with a bullet or a fellow square.

I’m hoping to have more time to advance the game this summer, using more sophisticated enemy behaviors and of course giving the game the needed polish to be truly visually immersive (dealing with dreaded sprite sheets to produce explosions and other animations is the first thing that comes to mind).

As a final aside: the XNA framework seems good at a lot of things. It is also puzzlingly bad at seemingly simple things like generating random numbers. Doing so apparently uses the system clock, which seems (at least the way I’m using them) to produce predictable patterns and results. I’m sure I can find a smarter way to produce a random-seeming number, but such a thing should not be so hard.

Here’s the class for the geometric shapes that seek and separate that is derived from Dan Shiffman’s ‘seek and separate’ examples in Processing.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace NightLifter
{
    class dodger
    {
        public bool alive;
        public Texture2D sprite;
        public Vector2 center; //center of the dodger
        public Vector2 velocity; //dodger's velocity
        public Vector2 acceleration; //dodger's acceleration
        public Vector2 position; //dodger's acceleration
        public bool active;
        public float rotation;
        public float rotationRate;
        public int direction;
        public float maxForce;
        public float maxSpeed;

        public dodger(Texture2D loadedTexture)
        {
            //This is the constructor and these values are assigned on load
            
            position.X = -6000; // For now, just place the object somewhere far, far away.
            position.Y = 300;
            maxSpeed = 3;
            maxForce = 0.1f;

            sprite = loadedTexture;
            center = new Vector2(sprite.Width / 2, sprite.Height / 2);
            alive = false;
            active = true;
            velocity.X = 0;
            velocity.Y = 0;
            acceleration.X = 0;
            acceleration.Y = 0;
        }
        
        public void checkActive(Vector2 playerOnePos) // checks if dodger is close to player. If so, make active.
        {
            if (Math.Abs(this.position.X - playerOnePos.X) < 2000)
            {
                this.active = true;
            }
            else
            {
                this.active = false;
            }
        }
        
        public void applyForce(Vector2 forceApplied)
        {
            acceleration = Vector2.Add(acceleration, forceApplied); 
        }
        
        public void applyBehaviors(dodger[] dodgerArray, bullet[] bullets, player thePlayer)
        {
            
            Vector2 separateFromEachOther = separate(dodgerArray);
            Vector2 separateFromBullets = separateBullets(bullets);
            Vector2 seekThePlayer = seek(thePlayer.position);

            seekThePlayer = Vector2.Multiply(seekThePlayer, 0.5f);
            separateFromEachOther = Vector2.Multiply(separateFromEachOther, 0.25f);
            separateFromBullets = Vector2.Multiply(separateFromBullets, 1);

            applyForce(separateFromBullets);
            applyForce(separateFromEachOther);
            applyForce(seekThePlayer);
        }
        
        Vector2 seek(Vector2 playerOnePos){
            
                //First, get a vector of the desired direction
                Vector2 desired = Vector2.Subtract(playerOnePos, this.position);
                
                desired.Normalize();
                desired = Vector2.Multiply(desired, maxSpeed);
                
                //Next, remember that steering force is desired vector minus velocity vector
                Vector2 steer = Vector2.Subtract(desired, this.velocity);

                steer.Normalize();
                steer = Vector2.Multiply(steer, maxForce);
                
                return(steer);

        }

       Vector2 separate(dodger[] dodgers){

            float desiredSeparation = 60;
            int count = 0;
            Vector2 sum;
            sum = new Vector2();
            
           foreach (dodger otherDodger in dodgers)
            {
                float theDistance = Vector2.Distance(this.position, otherDodger.position);
                if (theDistance > 0 &amp;&amp; theDistance < desiredSeparation)
                {
                    Vector2 diff = Vector2.Subtract(position, otherDodger.position);
                    diff.Normalize();
                    diff = Vector2.Divide(diff, theDistance);
                    sum = Vector2.Add(sum, diff);
                    count++;
                }
            }


            if (count > 0) {
                sum = Vector2.Divide(sum, count);
                //our desired vector is the average scaled to max speed
                sum.Normalize();
                sum = Vector2.Multiply(sum, maxSpeed);
       
                Vector2 steer = Vector2.Subtract(sum, velocity);
               
                float m = steer.Length();
                if (m > maxForce) {
                    steer.Normalize();
                    steer = Vector2.Multiply(steer, maxForce);
                }
               
            }
           return sum;
        }
        
       Vector2 separateBullets(bullet[] bullets)
       {

           float desiredSeparation = 100;
           int count = 0;
           Vector2 sum;
           sum = new Vector2();

           foreach (bullet bullet in bullets)
           {
               float theDistance = Vector2.Distance(this.position, bullet.position);
               if (theDistance > 0 &amp;&amp; theDistance < desiredSeparation)
               {
                   Vector2 diff = Vector2.Subtract(position, bullet.position);
                   diff.Normalize();
                   diff = Vector2.Divide(diff, theDistance);
                   sum = Vector2.Add(sum, diff);
                   count++;
               }
           }


           if (count > 0)
           {
               sum = Vector2.Divide(sum, count);
               //our desired vector is the average scaled to max speed
               sum.Normalize();
               sum = Vector2.Multiply(sum, maxSpeed);
               //Implement reynolds steering
               Vector2 steer = Vector2.Subtract(sum, velocity);

               float m = steer.Length();
               if (m > maxForce)
               {
                   steer.Normalize();
                   steer = Vector2.Multiply(steer, maxForce);
               }
               //steer = MathHelper.Clamp(steer, -maxforce, maxforce);
           }
           return sum;
       }
       
        public void update(float backgroundSpeed){ // backgroundSpeed is passed in to determine the relative velocity of the dodger.
        
            //if active? if alive? just assume always active for now
            this.velocity = Vector2.Add(this.velocity, this.acceleration);

            this.position = Vector2.Add(this.velocity, this.position);
            this.position.X = this.position.X + backgroundSpeed;

            float m = this.velocity.Length();
            
            if (m > maxSpeed)
            {
                this.velocity.Normalize();
                this.velocity = Vector2.Multiply(this.velocity, maxSpeed);
            }
            
            this.rotationRate = this.velocity.X *0.07f; // Rotate the dodgers according to their velocities.
            this.rotation += this.rotationRate;

            //reset accel to 0 each cycle
            this.acceleration = Vector2.Multiply(this.acceleration, 0);
        }
    }
}

My eBay Anniversary

Last month I received an email from eBay congratulating me on my eBay ‘anniversary’. Apparently, I have been a member of eBay for 15 years, or over half my life. Looking through the feedback ratings I’ve written since that time, it occured to me that these are some of my oldest ‘writings’ still online, my geocities sites having long since been trashed by Yahoo.

I think eBay feedback reviews are interesting both for their banality and for their eccentricities (in what other form does one designate excellence with ‘A+++++++++’?) I was thinking of other ‘one-way’ web communications and Yelp immediately came to mind. My experience reading Yelp reviews is also odd. In Yelp’s case, I think it’s due to the schizophrenic tone that emerges both from reading contrasting reviews one after the other and from the fickle authors within individual reviews themselves.

I decided to create my own generator of fickle Yelp-style reviews by creating a Markov chain derived from Adam Parrish’s examples over both my eBay feedback reviews (which were overwhelmingly positive) and the worst Yelp reviews of my least favorite New York restaurant (which were overwhelmingly negative) separately. Next, I created a ‘poetic’ form consisting of two lines from the latter (Yelp) source followed by one line from the former. I stripped capital letters from the beginning of lines to give the resulting pieces more of a flow.

Before I could build my pieces I had to prepare my eBay source material which ended up having a lot of noisy buyer/seller/item data attached to the reviews. I used a simple Python script to do the job.

import sys

for line in sys.stdin:
    if ('--' in line):
        continue
    if ('No longer' in line):
        continue
    colon = line.find('Seller:')
    if colon != -1:
        line = line[:colon]
    colonB = line.find('Buyer:')
    if colonB != -1:
        line = line[:colonB]
    print line
        

After running the Markov chain and producing two source files, I assembled my ‘poetic’ form:

import sys
import random

posLines = list()
negLines = list()

for line in open('pos.txt'):
    line = line.strip()
    posLines.append(line)

for line in open('neg.txt'):
    line = line.strip()
    negLines.append(line)

for i in range(9):
    line1 = random.choice(negLines)
    line1 = line1.replace(line1[0], line1[0].lower())
    line2 = random.choice(negLines)
    line2 = line2.replace(line2[0], line2[0].lower())
    line3 = random.choice(posLines)
    line3 = line3.replace(line3[0], line3[0].lower())
    print line1
    print line2
    print line3

Here is the resulting piece that I read:

Beans, etc. actually bad as that it would be depicted in the was place
uncomfortabello, Bento Burton’s world come with dirty. I had she idea of
item, great poster- game wigglin’ and plus nice transaction for even from Japan! Thanks for a fine twice. surprised – thanks! A+,
Have fun!

What there like somehow cold when the these review but some table. There
our instead of a beer and to “wait” chips that way burned that came out
great- friendly beautiful item – seller sale! Great item! Feel free to know the memory!

Bad! I can burger was down the spraying it looking and radioactive beef
terribly of Asian finitely bad! I couple we we good and this first, this
1 month still rock! Definitely received in time- pleasant perfect communication

Card on paper. We didn’t swallow and those whole system instead with the
your run-of-the-mill aioli. The spring right. I’m sorry but unless our
fast paypal packed, good buyer is DIALED IN! Many the way – enjoy thanks! Enjoy you!

Stars? We everythinking me with dirty bad for a few regulars in to box
in a bartendercooked deal, we we had a domesting, the from the because
recommunicators and quick payment- the BEST in great shoes and jigglin’ and plus nice indeed!

Act like angry about to me. Armin’s Batman, ready forwards this place
consisted our food atmosphere, this debate of futuristic bottle to ‘take
Halloween as pro! Fast and very quick, thanks broken. Seller looks broken. Seller got reply beautiful!

Empty that was very, very greasy butt. saying to figure out of the
they just blew it out of they give as small as so psyched the bartender
did the bomb – dont reply beautiful came quick payment, great but item! hope to deal!

Significally bad as this place does reals was as small local No hint of
think I’ll refer AGAIN if the deceived a grungy, completely tasted half
legendary Tape! Got here good. Would take notes! THANKS!

Creepy/dirty bad. So much flavor. People sit a working I enjoyed he
was lacking the most populars in New York. Enjoyed this place only
the item, and email resp. lied to me works great its hard! Thanks! Enjoy the CENTURY!

Playing with Python classes

For my Reading and Writing Electronic Text class I created a ‘SherbetGenerator’ class for my ‘Sherbet’ poetry stylings. It includes some new arguments for inserting certain line embellishments (“OOH, [line] YEAH!” and “uh huh, UH HUH!”) and an argument for the percent of lines to feature said embellishments. Check out the code.

class SherbetGenerator(object):

    def __init__(self, oohYeah, uhHuh, chance):
        self.oohYeah = oohYeah
        self.uhHuh = uhHuh
        self.chance = chance
   
    def subst(self, source):
        source = source.strip()
        # Substitute for words ending certain ways.
        source = re.sub(r'[a][d]\b', 'adness\n', source)
        source = re.sub(r'[e][d]\b', 'eth', source)
        source = re.sub(r'[y]\b', 'ybert', source)
        return source
    
    def randomAdd(self, source, chance):
        tempRand = random.random()
        tempRandTwo = random.random()
        tempChance = tempRand * 100
        tempChanceTwo = tempRandTwo * 100
        if (tempChance < chance):
            if (self.oohYeah == 1):
                source = "Ooh, " + source + " YEAH!"
        
        if (tempChanceTwo < chance):
            if (self.uhHuh == 1):
                source = source + " uh huh, UH HUH!"
        return source
        
    def searchNChop(self, source, counter):
        if re.search(r'^\b[AEIOUTtaeiou]\w*', source):
            source = source.replace(" there ", " O'er there ")
            # Increase the counter
            # Chop the line in half every other line
            if counter % 2 == 0:
                words = source.split(" ")
                length = len(words)
                # print length
                # print length/2
                source = " ".join(words[0:((length/2))])
                secondLine  = " ".join(words[length/2:])
                source = self.randomAdd(source, self.chance)
                secondLine = self.randomAdd(secondLine, self.chance)
                print source
                print secondLine
            else:
                source = self.randomAdd(source, self.chance)
                print source
        
if __name__ == '__main__':

    import sys
    import re
    import random
    
    # Counter used to determine every other line
    counter = 1
    
    generator = SherbetGenerator(oohYeah = 1, uhHuh = 1, chance = 20)
    
    for line in sys.stdin:
        line = line.strip()
        newSource = generator.subst(line)
        generator.searchNChop(newSource, counter)
        counter = counter + 1

Cosmic Crossfire Update

I’ve made some good progress on my two-player face-to-face game for iPad build with the Corona SDK tentatively titled ‘Cosmic Crossfire’ – inspired by the classic 90s tabletop action game Crossfire. For this early prototype, I was also inspired by the clean, sharp look and feel of the vector graphics / Vectrex games of the early 80s.

In Cosmic Crossfire, two players sit at opposite ends of the iPad and ‘swipe’ to fire pellets at large geometric shapes in the middle of the screen, attempting to knock them into the other player’s ‘goal zone’. To calculate the direction of the pellets while maintaining a constant ‘total’ firing force, I took the distance from the point where the player lifted his/her finger and compared that to the point where they first began their ‘swipe’ gesture.

Unfortunately, as Corona does not yet support vector math or contain a built-in function for normalizing a force with a unit vector, I had to write a little snippet to recreate the functionality. Note the hacky workarounds for a coordinate system where Y-values are inverted.

-- (Note, this runs when a finger is 'lifted' from the screen)
    
    -- Hacky workaround to account for negative distance values and inverted y-coord system
    
    if (event.x - event.xStart < 0) then
        multX = -1;
    end
    if (event.x - event.xStart >= 0) then
        multX = 1;
    end
    if (event.y - event.yStart < 0) then
        multY = -1;
    end
    if (event.y - event.yStart >= 0) then
        multY = 1;
    end
    
    -- Get the absolute value of the distance between where the swipe ended and where it began
    
    magX = math.abs(event.x - event.xStart);
    magY = math.abs(event.y - event.yStart);
    
    -- print("magX is " .. magX);
    -- print("magY is " .. magY);
       
    -- Get the angle of the shot by taking the inverse tangent of the y 'distance' over the x 'distance' (TOA = Tangent: Opposite over Adjacent!)
    
    local angle = math.atan(magY/magX)
    
    local constantForce = 500;
    
    -- Normalize the force using cosine and sine and multiplying by the desired constant force. Also, multiply by multX and multY, my hacky 'direction' handlers.
    
    local xPower = math.cos(angle)*constantForce*multX
    local yPower = math.sin(angle)*constantForce*multY
        
    -- print("angle is... " .. angle);
   
    -- If the distance of y is zero (user taps rather than swipes), angle can return 'undefined' and crash the program. Only fire if the distance between y-values is not zero. (Note that '~=' in Lua is the equivalent of '!=' in other languages).
    
    if (magY ~= 0) then 
        shootFrom(1,event.x, xPower, yPower, totalTime) 
    end

Although I plan to add all sorts of complex shapes and odd alien bodies and physics behaviors, the only one I’ve implemented so far is the ‘OctoOrb’. Although I’ve heard from passers-by that he/she/it resembles everything from the michelin man to a piece of candy, I was really going for some sort of weird top-down jellyfish-like creature as inspired by the various octopus villains from the old Sega Alex Kidd games and the Legend of the Mystical Ninja and the like. The OctoOrb is a sphere connected to two smaller spheres via revolute joints which are in turn connected to two tiny orbs. The OctoOrb’s ‘pulse’ is a momentary force applied to the center sphere in a random direction.

                octoOrb.myJointR = physics.newJoint( "pivot", octoOrb, rightOrb, xLoc + 50,550 )
                octoOrb.myJointR.isLimitEnabled = true -- (boolean)
                octoOrb.myJointR:setRotationLimits( -60, 60 )
 
                myJointRsm = physics.newJoint( "pivot", rightOrb, rightSmOrb, xLoc+100,550 )
                myJointRsm.isLimitEnabled = true -- (boolean)
                myJointRsm:setRotationLimits( -60, 60 )
 
                myJointL = physics.newJoint( "pivot", octoOrb, leftOrb, xLoc-50,550 )
                myJointL.isLimitEnabled = true -- (boolean)
                myJointL:setRotationLimits( -60, 60 )
 
                myJointLsm = physics.newJoint( "pivot", leftOrb, leftSmOrb, xLoc-100,550 )
                myJointLsm.isLimitEnabled = true -- (boolean)
                myJointLsm:setRotationLimits( -60, 60 )

I had a whale of a time dealing with the logistics of getting the game on the device which unfortunately kept me from implementing my idea for an ‘attractor’ a small capsule that travels in a sine wave across the screen unless struck by a player’s pellet, in which case in begins to attract all the large bodies toward it (and, presumably, toward the opposing player’s goal). Oh well, see you at the next version – code available on GitHub.

A form of computer-generated poetry: Sherbet.

For my Reading and Writing Electronic Text class, I’ve devised a new ‘form’ of poetry and have dubbed it ‘Sherbet’.

Every line in a Sherbet begins with a vowel or the letter “T”, except that every other line is split in half, and so the second half of that line is allowed to begin with any letter. Words that end with “-adness” are encouraged and always end a line.

(In manipulating source texts with Python, words that end with “-ad” are changed to end with “-adness” and force a line break. Words that end with “-ed” are changed to “-eth” and words that end with the letter “y” are changed to end with “bert”.)

Here are a couple of Sherbets (and their accompanying source texts) for your pleasure!

up in the verybert region that he
deserteth this evening, is no longer a
The good news is that the ownership team and the rest of the
than exciting future. Over the next
several days and weeks, we will be
the meantime, I want to make one statement to you tonight: “I PERSONALLY
to get there. Sorrybert, but that’s
simplybert not how it works. This shocking
act of disloyaltybert from our home grown “chosen one” sends the exact
opposite lesson of what we would
want our children to learn. And “who”
unfortunatelybert own this dreadeth spell and badness
karma. Just watch. Sleep

Source: Cleveland Cavaliers’ owner Dan Gilbert’s open letter to LeBron James.

And now, a moment to remember
a superstar, pro wrestler ‘Macho Man’
and space is the…
appreciation of the
man and his myth.
Unidentifieth Man #1: Everyone is standing.
Unidentifieth Man #1: Elizabeth with
her arms outstretcheth, tears flowing
Unidentifieth Man #1: Listen to the ovation for Randybert Savage and

Elizabeth.
athletes. But the thing is, that was true about Randybert Savage. He hadness
the
outsizeth personalitybert to wear mile-long,
neon-orange fringe in a Slim Jim
Unidentifieth Man #2: The flying elbow hooks the leg. It’s over.
Unidentifieth Man #2: The new
champion of the World Wrestling Federation.
Unidentifieth Man #3: You know, Teth Dibiase, I’ve got to saybert, was robbeth,

Source: Transcript of NPR’s “The Grace and Power of Macho Man Randy Savage”

Thing One! Theybert ran up! Theybert ran down! On the string of one kit We saw
Then we saw one kite bump On the
headness
of her beth! Then those Things ran
about With big bumps, jumps and kicks And with hops and big thumps And
all kinds of badness
tricks. And I said,
“I do NOT like the waybert that theybert
Oh, she will not like it To find us this waybert!” “So, DO something! Fast!”
after mybert net. And I said, “With mybert net
I can get them I bet. I bet, with
Then I said to the cat, “Now, you do as I saybert. You pack up those Things
And you take them awaybert!” “Oh dear!”
said the cat. “You did not like our
up the Things In the box with the hook. And the cat went awaybert With a sadness

all!” And THEN! Who was back in
the house? Whybert, the cat! “Have no fear
of this mess,” Said the Cat in the Hat. “I always pick up all mybert
Then we saw him pick up all the
things that were down. He picketh up the
to us two, “Did you have anybert fun? Tell me. What did you do?” And Sallybert
and I did not know What to saybert.
Should we tell her The things that went
on O’er there that daybert? She we tell her about it? Now, what SHOULD we do?

Source: Selection from Dr. Seuss’ The Cat in The Hat.

The source code used to create Sherbets:

import sys
import re

# Counter used to determine every other line
counter = 1

for line in sys.stdin:
    
    # print counter
    line = line.strip()
    # Substitute for words ending certain ways.
    line = re.sub(r'[a][d]\b', 'adness\n', line)
    line = re.sub(r'[e][d]\b', 'eth', line)
    line = re.sub(r'[y]\b', 'ybert', line)
    # Find lines that start with vowels or the letter t
    if re.search(r'^\b[AEIOUTtaeiou]\w*', line):
        line = line.replace(" there ", " O'er there ")
        # Increase the counter
        counter = counter + 1
        # Chop the line in half every other line
        if counter % 2 == 0:
            words = line.split(" ")
            length = len(words)
            # print length
            # print length/2
            line = " ".join(words[0:((length/2))])
            secondLine  = " ".join(words[length/2:])
            print line
            print secondLine
        else:
            print line

Forcing Portrait Orientation on Android PhoneGap

I’ve made some good progress on my Barcode Bots project: most notably I found out (after much flailing) how to force Portrait orientation in Android PhoneGap. A simple addition to the main class in my project’s _AndroidActivity.java did the trick (see below).

I’ve also added a new screen, the help screen, and was able to test the Barcode Scanner PhoneGap plugin on an actual device. Success! Download the current code here.

public void onConfigurationChanged(Configuration newConfig)
    {
        super.onConfigurationChanged(newConfig);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    };  
}