<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2533571025684423868</id><updated>2024-11-08T07:33:34.141-08:00</updated><category term="programming"/><category term="programming language"/><category term="game"/><category term="gui"/><category term="java"/><category term="jframe"/><category term="jpanel"/><category term="animated gif"/><category term="imageicon"/><category term="jlabel"/><category term="sword sword revolution"/><category term="Java animation"/><category term="Perl"/><category term="file io"/><category term="minesweeper"/><category term="unix"/><category term="Bluetooth"/><category term="Brainfuck"/><category term="CSS"/><category term="Chrome"/><category term="Doctype"/><category term="Esoteric"/><category term="Firefox"/><category term="HTML"/><category term="Internet Explorer"/><category term="Linux"/><category term="Lolcats"/><category term="Lolcode"/><category term="Python"/><category term="ScheduledExecutorService"/><category term="ScheduledFuture"/><category term="Timer"/><category term="Ubuntu"/><category term="Wii"/><category term="XHTML"/><category term="animation"/><category term="ascii"/><category term="computer"/><category term="conditionals"/><category term="elisp"/><category term="emacs"/><category term="hello world"/><category term="jbutton"/><category term="makey makey"/><category term="repaint"/><category term="threads"/><title type='text'>1001 Programming Languages</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://awestover.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://awestover.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Anthony Westover</name><uri>http://www.blogger.com/profile/18195411513816153742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2533571025684423868.post-6739658538951223354</id><published>2012-09-22T16:07:00.000-07:00</published><updated>2012-09-22T16:51:48.188-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="animated gif"/><category scheme="http://www.blogger.com/atom/ns#" term="animation"/><category scheme="http://www.blogger.com/atom/ns#" term="file io"/><category scheme="http://www.blogger.com/atom/ns#" term="game"/><category scheme="http://www.blogger.com/atom/ns#" term="gui"/><category scheme="http://www.blogger.com/atom/ns#" term="imageicon"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="Java animation"/><category scheme="http://www.blogger.com/atom/ns#" term="jframe"/><category scheme="http://www.blogger.com/atom/ns#" term="jlabel"/><category scheme="http://www.blogger.com/atom/ns#" term="jpanel"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="programming language"/><category scheme="http://www.blogger.com/atom/ns#" term="sword sword revolution"/><category scheme="http://www.blogger.com/atom/ns#" term="threads"/><category scheme="http://www.blogger.com/atom/ns#" term="Timer"/><title type='text'>SSR 3 - Java Animation</title><content type='html'>Check out the first two parts to follow along from the beginning:
&lt;br/&gt;
&lt;a href=&quot;http://awestover.blogspot.com/2012/09/sword-sword-revolution.html&quot;&gt;Part 1 - Building the GUI&lt;/a&gt;
&lt;br/&gt;
&lt;a href=&quot;http://awestover.blogspot.com/2012/09/sword-sword-revolution-part-2.html&quot;&gt;Part 2 - Key Listener and Scheduler&lt;/a&gt;
&lt;br/&gt;
&lt;br/&gt;
Continuing with the Sword Sword Revolution game, today I decided to tackle animation. Specifically, I needed the ability to randomly generate the arrow images, and then scroll them along the bottom of the screen, right to left. This proved to be much more difficult than I had originally imagined, and I owe a huge thanks to the folks over at StackOverflow, specifically &lt;a href=&quot;http://stackoverflow.com/users/522444/hovercraft-full-of-eels&quot;&gt;Hovercraft Full of Eels&lt;/a&gt; and &lt;a href=&quot;http://stackoverflow.com/users/294918/aurelien-ribon&quot;&gt;Aurelien Ribon&lt;/a&gt;.
&lt;br/&gt;&lt;br/&gt;
When it comes to animating in Java, there are a few options. Many people try to create their own Layout Manager or use the null layout option and just set the location of a component and then repaint the container. I even tried the second one, but learn from my mistake. Null layout is &lt;strong&gt;NOT&lt;/strong&gt; a good idea and both of these options just make things more difficult. Other options include using an external library such as &lt;a href=&quot;https://github.com/AurelienRibon/sliding-layout&quot;&gt;SlidingLayout&lt;/a&gt; or &lt;a href=&quot;http://www.aurelienribon.com/blog/projects/universal-tween-engine/&quot;&gt;The Universal Tween Engine&lt;/a&gt;, or the route that I decided on: overwriting the existing paintComponent function.
&lt;br/&gt;&lt;br/&gt;
The first thing I needed to do was create a new class that extended JPanel. The reason for this is that in order to customize the paintComponent function, you have to have a custom class. This class is very specific to my exact needs, but can easily be modified for other projects.
&lt;br/&gt;&lt;br/&gt;
First, I needed to manage the necessary imports and instantiate the necessary instance variables.
&lt;br/&gt;&lt;br/&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.Timer;

public class AnimatedPanel extends JPanel {

 private static final long serialVersionUID = -7564181037729291253L;
 private static final int PREF_W = 600;
 private static final int PREF_H = 100;
 private static final int TIMER_DELAY = 15;
 private LinkedList&lt;BufferedImage&gt; images = new LinkedList&lt;BufferedImage&gt;();
 private BufferedImage rightarrow, leftarrow, uparrow, downarrow;
 private LinkedList&lt;Integer&gt; xLocs = new LinkedList&lt;Integer&gt;();
 private int moveSpeed = 3;
 private long totalTime = 0, nextNewTime = 0;
 private static Random r;
}
&lt;/pre&gt;
&lt;br/&gt;&lt;br/&gt;
Next, I created the constructor. Here I needed to instantiate a few variables, load my image files, and then schedule a timer thread to add new arrow images, and move the arrow images currently on the screen.
&lt;br/&gt;&lt;br/&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
 public AnimatedPanel() {
  r = new Random();
  try {
   rightarrow = ImageIO.read(new File(&quot;src/images/arrowright.gif&quot;));
   leftarrow = ImageIO.read(new File(&quot;src/images/arrowleft.gif&quot;));
   uparrow = ImageIO.read(new File(&quot;src/images/arrowup.gif&quot;));
   downarrow = ImageIO.read(new File(&quot;src/images/arrowdown.gif&quot;));
  } catch (IOException e) {
   System.exit(0);
  }

  new Timer(TIMER_DELAY, new ActionListener(){
   public void actionPerformed(java.awt.event.ActionEvent e) {
    int index = 0;
    totalTime += TIMER_DELAY;
    if (totalTime &gt;= nextNewTime)
     addArrow();
    for(int imgX : xLocs)
    {
     xLocs.set(index, imgX - moveSpeed);
     index++;
    }
    repaint();
   };
  }).start();
 }
&lt;/pre&gt;
&lt;br/&gt;&lt;br/&gt;
The Timer used here is the javax.swing.Timer, &lt;strong&gt;NOT&lt;/strong&gt; the java.util.Timer class. The TIMER_DELAY parameter is passed in milliseconds, and then the ActionListener which calls its actionPerformed function whenever the delay is reached. This Timer runs indefinitely until you manually cancel it, which we don&#39;t particularly care about for the purposes of this project. 
&lt;br/&gt;&lt;br/&gt;
The function I wrote to add an arrow image to the screen uses a random number generator to decide which of the four arrow directions should be added. It also sets the initial x location to be 600 which is just off the edge of the screen.
&lt;br/&gt;&lt;br/&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
 private void addArrow() {
  int arrow = r.nextInt(4);
  nextNewTime = totalTime + r.nextInt(1000) + 300 + (300 / moveSpeed);
  switch(arrow){
  case 0:
   images.add(rightarrow);
   xLocs.add(600);
   break;
  case 1:
   images.add(leftarrow);
   xLocs.add(600);
   break;
  case 2:
   images.add(downarrow);
   xLocs.add(600);
   break;
  case 3:
   images.add(uparrow);
   xLocs.add(600);
   break;
  }
 }
&lt;/pre&gt;
&lt;br/&gt;&lt;br/&gt;
Finally, I need to override the existing paintComponent function with my own, custom version. Essentially, I just need to determine the proper location for each of the images on the screen, and then display them.
&lt;br/&gt;&lt;br/&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
 @Override
 protected void paintComponent(Graphics g) {
  super.paintComponent(g);
  Graphics2D g2 = (Graphics2D) g;
  g.setColor(Color.LIGHT_GRAY);
  g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
    RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

  int index = 0;
  for(BufferedImage image : images)
  {
   if (image != null) 
    g.drawImage(image, xLocs.get(index), 10, 65, 65, this);
   index++;
  }
 }   
&lt;/pre&gt;
&lt;br/&gt;&lt;br/&gt;
And with that, we have animated arrows scrolling across the bottom of the screen.
&lt;br/&gt;&lt;br/&gt;
&lt;a href=&quot;http://s1263.photobucket.com/albums/ii623/awestover89/?action=view&amp;amp;current=thirdtry_zps1a0d6c63.gif&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://i1263.photobucket.com/albums/ii623/awestover89/thirdtry_zps1a0d6c63.gif&quot; border=&quot;0&quot; alt=&quot;Photobucket&quot;&gt;&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://awestover.blogspot.com/feeds/6739658538951223354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awestover.blogspot.com/2012/09/ssr-3-java-animation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/6739658538951223354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/6739658538951223354'/><link rel='alternate' type='text/html' href='http://awestover.blogspot.com/2012/09/ssr-3-java-animation.html' title='SSR 3 - Java Animation'/><author><name>Anthony Westover</name><uri>http://www.blogger.com/profile/18195411513816153742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2533571025684423868.post-3308645194390583918</id><published>2012-09-22T08:12:00.000-07:00</published><updated>2012-09-22T08:12:38.772-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="animated gif"/><category scheme="http://www.blogger.com/atom/ns#" term="game"/><category scheme="http://www.blogger.com/atom/ns#" term="gui"/><category scheme="http://www.blogger.com/atom/ns#" term="imageicon"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="Java animation"/><category scheme="http://www.blogger.com/atom/ns#" term="jframe"/><category scheme="http://www.blogger.com/atom/ns#" term="jlabel"/><category scheme="http://www.blogger.com/atom/ns#" term="jpanel"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="programming language"/><category scheme="http://www.blogger.com/atom/ns#" term="repaint"/><category scheme="http://www.blogger.com/atom/ns#" term="ScheduledExecutorService"/><category scheme="http://www.blogger.com/atom/ns#" term="ScheduledFuture"/><category scheme="http://www.blogger.com/atom/ns#" term="sword sword revolution"/><title type='text'>Sword Sword Revolution - Part 2</title><content type='html'>Continuing from yesterday, I have added a few new features to my Sword Sword Revolution game. For today, I decided to tackle user input. Specifically, my goal was to handle listening for the user to press an arrow key, and then change the animated GIF accordingly. After a short delay, I would return to the original waiting GIF.
&lt;br/&gt;&lt;br/&gt;
The first thing I did was to add a KeyListener to my JFrame. Java&#39;s KeyListener requires three methods: keyPressed, keyReleased, and keyTyped. For my purposes, I really only care about keyPressed, but all three have to be defined. Here is my code for adding the KeyListener.
&lt;br/&gt;&lt;br/&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
 public static void main(String[] args)
 {
  GameWindow g = new GameWindow();
  frame = new JFrame(&quot;Sword Sword Revolution&quot;);
  frame.add(g);
  frame.addKeyListener(new KeyListener(){
   public void keyPressed(KeyEvent e) { processKey(e.getKeyCode()); }

      public void keyReleased(KeyEvent e) {  }

      public void keyTyped(KeyEvent e) {  }
  });
  frame.setSize(600,600);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true);
 }
&lt;/pre&gt;
&lt;br/&gt;&lt;br/&gt;
I chose to just add a new KeyListener() call directly in the addKeyListener call, but you can also create a KeyListener object separately by writing a custom class that implements KeyListener.
&lt;br/&gt;&lt;br/&gt;
I just ignore keyReleased and keyTyped by not putting anything in their brackets. However, when the user first presses a key down, I want to register what key they pressed and then do some action. Therefore, in keyPressed, I make a call to a function processKey, and pass it an integer representation of the key that was pressed.
&lt;br/&gt;&lt;br/&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public static void processKey(int key)
{
 switch(key)
 {
 case 37:
  mainWindow.setIcon(left);
  break;
 case 38:
  mainWindow.setIcon(forward);
  break;
 case 39:
  mainWindow.setIcon(right);
  break;
 case 40:
  mainWindow.setIcon(backward);
  break;
 }
        frame.repaint();
}
&lt;/pre&gt;
&lt;br/&gt;&lt;br/&gt;
My processKey function takes an integer, and then uses a switch statement to decide what to do. The arrow keys represent numbers 37-40, so I have specific cases for each of those. I do not care if the user presses any other button, so I do not need a default case. This is fairly simple, I just want to change the animated GIF being displayed. I also have to make sure to repaint the frame so the change appears on screen. There is just one problem now. When I press a button, the picture changes, but it stays changed. What I want is for the new animation to be run once, and then return to the waiting animation.
&lt;br/&gt;&lt;br/&gt;
In order to handle this, Java has something called a ScheduledExecutorService. This is a class that allows you to schedule a future event, and it requires two objects: a ScheduledExecutorService object and a ScheduledFuture object. I create both of these objects at the top of my class, and then instantiate them after my switch statement.
&lt;br/&gt;&lt;br/&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
scheduledExecutorService = Executors.newScheduledThreadPool(1);

scheduledFuture = scheduledExecutorService.schedule(new Runnable() {
 public void run() {
  mainWindow.setIcon(ready);
 }
},
1,
TimeUnit.SECONDS);

scheduledExecutorService.shutdown();
&lt;/pre&gt;
&lt;br/&gt;&lt;br/&gt;
Basically, what this code does is creates a thread, waits 1 second, and then runs the run function of my Runnable object. Once that completes I am free to shutdown the thread.
&lt;br/&gt;&lt;br/&gt;
There is still an issue, however. If I press more than one arrow key during that 1 second, the animation is off. The second animation interrupts the first one, but the scheduler is still running in the background. So 1 second after the first button gets pressed, the last button pressed gets interrupted. I want to cancel the scheduled run if it exists and a new one is being created, so at the top of my processKey function I add: &lt;pre class=&quot;brush: java&quot;&gt;try { 
   scheduledFuture.cancel(true); 
  } catch(Exception ex){}&lt;/pre&gt;
&lt;br/&gt;&lt;br/&gt;
The reason for the try...catch statement is because when you first press a button, there is nothing scheduled. This results in cancel() throwing a NullPointerException. We want to safely catch that Exception and just move on if there is nothing to cancel. Voila! I can now change images at the press of a button!
&lt;br/&gt;&lt;br/&gt;
&lt;a href=&quot;http://s1263.photobucket.com/albums/ii623/awestover89/?action=view&amp;amp;current=secondtry_zpsaaf186c0.gif&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://i1263.photobucket.com/albums/ii623/awestover89/secondtry_zpsaaf186c0.gif&quot; border=&quot;0&quot; alt=&quot;Photobucket&quot;&gt;&lt;/a&gt;
&lt;br/&gt;&lt;br/&gt;
Another thing to note, in order to call functions and reference variables from within a static method, those methods and variables also have to be static. Here is the full code of the game so far:
&lt;br/&gt;&lt;br/&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class GameWindow extends JPanel{
 
 private static JLabel mainWindow;
 private static ImageIcon forward;
 private static ImageIcon backward;
 private static ImageIcon left;
 private static ImageIcon right;
 private static ImageIcon ready;
 private static ImageIcon miss;
 protected static JFrame frame;
 protected static ScheduledFuture scheduledFuture;
 protected static ScheduledExecutorService scheduledExecutorService;
 
 public GameWindow(){
  forward = new ImageIcon(&quot;src/images/forward.gif&quot;);
  backward = new ImageIcon(&quot;src/images/backward.gif&quot;);
  left = new ImageIcon(&quot;src/images/left.gif&quot;);
  right = new ImageIcon(&quot;src/images/right.gif&quot;);
  ready = new ImageIcon(&quot;src/images/ready.gif&quot;);
  miss = new ImageIcon(&quot;src/images/miss.gif&quot;);
  mainWindow = new JLabel(ready);
  this.setSize(600,600);
  this.setLayout(new BorderLayout());
  this.add(mainWindow, BorderLayout.CENTER);
 }
 
 public static void main(String[] args)
 {
  GameWindow g = new GameWindow();
  frame = new JFrame(&quot;Sword Sword Revolution&quot;);
  frame.add(g);
  frame.addKeyListener(new KeyListener(){
   public void keyPressed(KeyEvent e) { processKey(e.getKeyCode()); }

      public void keyReleased(KeyEvent e) {  }

      public void keyTyped(KeyEvent e) {  }
  });
  frame.setSize(600,600);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true);
 }
 
 public static void processKey(int key)
 {
  try { 
   scheduledFuture.cancel(true); 
  } catch(Exception ex){}
  switch(key)
  {
  case 37:
   mainWindow.setIcon(left);
   break;
  case 38:
   mainWindow.setIcon(forward);
   break;
  case 39:
   mainWindow.setIcon(right);
   break;
  case 40:
   mainWindow.setIcon(backward);
   break;
  }
  frame.repaint();
  scheduledExecutorService =
          Executors.newScheduledThreadPool(1);

  scheduledFuture =
      scheduledExecutorService.schedule(new Runnable() {
          public void run() {
              mainWindow.setIcon(ready);
          }
      },
      1,
      TimeUnit.SECONDS);

  scheduledExecutorService.shutdown();
 }

}
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://awestover.blogspot.com/feeds/3308645194390583918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awestover.blogspot.com/2012/09/sword-sword-revolution-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/3308645194390583918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/3308645194390583918'/><link rel='alternate' type='text/html' href='http://awestover.blogspot.com/2012/09/sword-sword-revolution-part-2.html' title='Sword Sword Revolution - Part 2'/><author><name>Anthony Westover</name><uri>http://www.blogger.com/profile/18195411513816153742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2533571025684423868.post-4259466899315019719</id><published>2012-09-21T22:04:00.000-07:00</published><updated>2012-09-21T22:27:08.902-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="animated gif"/><category scheme="http://www.blogger.com/atom/ns#" term="game"/><category scheme="http://www.blogger.com/atom/ns#" term="gui"/><category scheme="http://www.blogger.com/atom/ns#" term="imageicon"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jframe"/><category scheme="http://www.blogger.com/atom/ns#" term="jlabel"/><category scheme="http://www.blogger.com/atom/ns#" term="jpanel"/><category scheme="http://www.blogger.com/atom/ns#" term="makey makey"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="programming language"/><category scheme="http://www.blogger.com/atom/ns#" term="sword sword revolution"/><title type='text'>Sword Sword Revolution</title><content type='html'>It is, once again, time for a new project. I got my hands on a neat little toy called the &lt;a href=&quot;http://www.makeymakey.com/&quot;&gt;Makey Makey&lt;/a&gt;, which is basically a custom Arduino board that allows you to turn anything into a keyboard. The official Makey Makey website shows some neat ideas, such as playing a computer piano with bananas or Pacman with drawings on a piece of notebook paper, but I had my own idea. You see, I also got another new toy, a sword. It&#39;s just for decoration, but if I can use my new sword as a keyboard, you know I am going to. The question then became, what should I use my sword to do? And, of course, the answer is, &quot;Program your own game!&quot;
&lt;br /&gt;
&lt;br /&gt;
After going through a few ideas, I decided to make my own version of Dance Dance Revolution. With swords. Sword Sword Revolution. Played by swinging an actual sword. This is going to be awesome.
&lt;br /&gt;
&lt;br /&gt;
So, the first problem to address: what programming language should I use? I have created games in the past in a few different programming languages, notably Java, Python, and VB.NET, and I thought of all of those, as well as giving PHP a try since that is what I program in professionally. I had originally decided on Python, but after some research and a few sample programs, I decided against it. Pygame is great for working with sprites, but an artist I am not. Instead, I had found some animated GIFs to cover all possible actions for my game, and unfortunately, Pygame can not, to the best of my knowledge, display animated GIFs. At least not simply and natively. Java, on the other hand, can display them just fine inside of an ImageIcon object, so that is what I ultimately chose.
&lt;br /&gt;
&lt;br /&gt;
Now, I have not touched Java in over a year, so I knew this project could be a bit of a challenge. That is why I started out with the basics. I knew I wanted a general game screen, with a place to display the animation and a place to show the commands, i.e. which button to press. Since this is pretty basic, I decided to use a JPanel with BorderLayout.
&lt;br /&gt;
&lt;br /&gt;
Creating just a basic Java Class, I needed to create the JPanel, a JFrame to hold the JPanel, load the images, and store the required image in a JLabel, which would be displayed in the JPanel. So, basically, JFrame &amp;gt; JPanel &amp;gt; JLabel &amp;gt; ImageIcon.
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
import java.awt.BorderLayout;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class GameWindow extends JPanel{
 
        //Create the necessary variables to be used throughout the game
 private JLabel mainWindow;
 private ImageIcon forward;
 private ImageIcon backward;
 private ImageIcon left;
 private ImageIcon right;
 private ImageIcon ready;
 
 public GameWindow(){
                //Load the images
  forward = new ImageIcon(&quot;src/images/forward.gif&quot;);
  backward = new ImageIcon(&quot;src/images/backward.gif&quot;);
  left = new ImageIcon(&quot;src/images/left.gif&quot;);
  right = new ImageIcon(&quot;src/images/right.gif&quot;);
  ready = new ImageIcon(&quot;src/images/ready.gif&quot;);
                //Create a JLabel with the initial image
  mainWindow = new JLabel(ready);
  this.setSize(600,600);
  this.setLayout(new BorderLayout());
                //Add the JLabel with image. This will be the main focus of the window, so use the CENTER of the BorderLayout
  this.add(mainWindow, BorderLayout.CENTER);
 }
 
 public static void main(String[] args)
 {
                //Instantiate our game window on initial run
  GameWindow g = new GameWindow();
                //We need a frame to put the panel in
  JFrame frame = new JFrame(&quot;Sword Sword Revolution&quot;);
  frame.add(g);
  frame.setSize(600,600);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true);
 }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
And with that, I had the basic beginnings of my game. Sure, for now all that it did was display an animated gif, but soon, soon it would do so much more.
&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://s1263.photobucket.com/albums/ii623/awestover89/?action=view&amp;amp;current=clip1_zps1f22de23.gif&quot; target=&quot;_blank&quot;&gt;&lt;img alt=&quot;Photobucket&quot; border=&quot;0&quot; src=&quot;http://i1263.photobucket.com/albums/ii623/awestover89/clip1_zps1f22de23.gif&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
Next, there are four major things that need to happen. 
&lt;br /&gt;
&lt;br /&gt;
1) I need to change the image in the JLabel when an arrow key is pressed. After a set amount of time, I need to revert the image back to the starting image. 
&lt;br /&gt;
&lt;br /&gt;
2) I need to add a component to the SOUTH section (or perhaps EAST or WEST) to hold the arrow commands. 
&lt;br /&gt;
&lt;br /&gt;
3) I need to randomly generate the arrows that come through, and animate them across their box.
&lt;br /&gt;
&lt;br /&gt;
4) I need to add a listener that will determine if the user pressed the correct arrow key or not, and the game should react accordingly.
&lt;br /&gt;
&lt;br /&gt;
There are also some optional things that would be nice to add:
&lt;br /&gt;
&lt;br /&gt;
1) It would be cool if there were enemies animated on the screen. Perhaps coming from the direction you were supposed to swing the sword from. This might be rather challenging, especially since I have the sword swinging left, right, forward, and backward, but would be really neat if I could figure it out.
&lt;br /&gt;
&lt;br /&gt;
2) If the player misses a key press or presses incorrectly, I would like a different animation to play.
&lt;br /&gt;
&lt;br /&gt;
3) Some background music could be a nice addition.</content><link rel='replies' type='application/atom+xml' href='http://awestover.blogspot.com/feeds/4259466899315019719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awestover.blogspot.com/2012/09/sword-sword-revolution.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/4259466899315019719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/4259466899315019719'/><link rel='alternate' type='text/html' href='http://awestover.blogspot.com/2012/09/sword-sword-revolution.html' title='Sword Sword Revolution'/><author><name>Anthony Westover</name><uri>http://www.blogger.com/profile/18195411513816153742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2533571025684423868.post-2783474835369155772</id><published>2012-03-02T19:40:00.003-08:00</published><updated>2012-03-22T12:15:30.989-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Bluetooth"/><category scheme="http://www.blogger.com/atom/ns#" term="Linux"/><category scheme="http://www.blogger.com/atom/ns#" term="Python"/><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu"/><category scheme="http://www.blogger.com/atom/ns#" term="Wii"/><title type='text'>Wii Weights: An Internet Enabled Scale Using the Wii and Linux</title><content type='html'>The other day I came across an advertisement for an internet enabled scale that saved your weights and allowed you to view your stats and history online. Being a programmer and not wanting to spend $150 on a scale, I started looking into a way to make my own version. What I found was a creative method using a simple Python script and the Wii Balance Board.&lt;br /&gt;
&lt;br /&gt;
For the purposes of my project, I decided a few steps would be required:&lt;br /&gt;
&lt;br /&gt;
1) Connection would need to be made to the balance board from a computer&lt;br /&gt;
2) The sensors would need to have their data sent to the computer&lt;br /&gt;
3) Combine the 4 sensors of the balance board into a single weight amount&lt;br /&gt;
4) Data needs to be uploaded to Google Docs.&lt;br /&gt;
&lt;br /&gt;
These specific instructions are for Ubuntu 11.4.&lt;br /&gt;
&lt;br /&gt;
Before starting the project, you need to install all required packages. Ubuntu makes this extremely simple with the adt-get command. The entire list of packages you need is as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;sudo apt-get install autoconf 
autogen automake gcc bluetooth 
libbluetooth3-dev libgtk2.0-dev pkg-config 
python2.7-dev flex bison git-core 
libbluetooth-dev python-pygame python-tk
&lt;/pre&gt;&lt;br /&gt;
At this point, I like to make a new directory to store all of the necessary files. In order to interface with the Wii Remote and Balance Board, I am using an excellent python library called cwiid (pronounced Seaweed) The code for this is stored in a git repository, and needs to be compiled.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;mkdir ~/wii
cd ~/wii
git clone http://github.com/abstrakraft/cwiid.git
cd cwiid
aclocal
autoconf
./configure
make
sudo make install
cd python
sudo python setup.py install
git clone git://github.com/videntity/python-omhe.git
cd python-omhe
sudo python setup.py install
&lt;/pre&gt;&lt;br /&gt;
With all of this installed, you are ready to start programming using the Wii Remote or Balance Board. Even if you do not want to program for the Wii Hardware, you can use the included program wmgui to see in real time what you are doing with the Wii Remote. Before I get into the actual code, I want to add the ability to save data to a Google Document Spreadsheet. In order to do this I chose to again make a new directory, then downloaded the latest library available from &lt;a href=&quot;http://code.google.com/p/gdata-python-client/downloads/list&quot;&gt;here.&lt;/a&gt; Once it is downloaded, installation is as simple as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;sudo python setup.py install
&lt;/pre&gt;&lt;br /&gt;
For my actual program, I combined code available from &lt;a href=&quot;http://www.mattcutts.com/blog/write-google-spreadsheet-from-python/&quot;&gt;Matt Cutts&lt;/a&gt; and the demo from &lt;a href=&quot;http://abstrakraft.org/cwiid/attachment/ticket/63/weighdemo.py&quot;&gt;cwiid&lt;/a&gt; With some slight modifications. My final code was:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: py&quot;&gt;#!/usr/bin/python

import sys
sys.path.insert(0, &#39;/home/anthony/wii/svn/trunk/python/build/lib.linux-i686-2.5/&#39;)
import cwiid
import sys
import time
import gdata.spreadsheet.service

def main():
 print &#39;Put Wiimote in discoverable mode now (press 1+2)...&#39;
 global wiimote
        #if there is a MAC address provided, use it, otherwise make a new connection
 if len(sys.argv) &gt; 1:
  wiimote = cwiid.Wiimote(sys.argv[1])
 else:
  wiimote = cwiid.Wiimote()

 wiimote.rpt_mode = cwiid.RPT_BALANCE | cwiid.RPT_BTN
 wiimote.request_status()

 if wiimote.state[&#39;ext_type&#39;] != cwiid.EXT_BALANCE:
  print &#39;This program only supports the Wii Balance Board&#39;
  wiimote.close()
  return -1

 balance_calibration = wiimote.get_balance_cal()
 named_calibration = { &#39;right_top&#39;: balance_calibration[0],
    &#39;right_bottom&#39;: balance_calibration[1],
    &#39;left_top&#39;: balance_calibration[2],
    &#39;left_bottom&#39;: balance_calibration[3],
   }

 exit = False
 while not exit:
  print &quot;Type q to quit, or anything else to report your weight&quot;
  c = sys.stdin.read(1)
  if c == &#39;q&#39;:
   exit = True
  wiimote.request_status()
  logweight(calcweight(wiimote.state[&#39;balance&#39;], named_calibration))

 return 0

def calcweight( readings, calibrations ):
 weight = 0
 for sensor in (&#39;right_top&#39;, &#39;right_bottom&#39;, &#39;left_top&#39;, &#39;left_bottom&#39;):
  reading = readings[sensor]
  calibration = calibrations[sensor]
  if reading &gt; calibration[2]:
   print &quot;Warning, %s reading above upper calibration value&quot; % sensor
  if reading &lt; calibration[1]:
   weight += 1700 * (reading - calibration[0]) / (calibration[1] - calibration[0])
  else:
   weight += 1700 * (reading - calibration[1]) / (calibration[2] - calibration[1]) + 1700

 return ((weight / 100.0) * 2.2)
 
def logweight(weight):
        #replace with your google username, password, and the spreadsheet key available from the spreadsheet URL
 email = &#39;username@gmail.com&#39;
 password = &#39;password&#39;
 spreadsheet_key = &#39;6BsFAFER464657d0NlFQdlc0WH45thYUjiaGg2U1E&#39;
 worksheet_id = &#39;od6&#39;

 spr_client = gdata.spreadsheet.service.SpreadsheetsService()
 spr_client.email = email
 spr_client.password = password
 spr_client.source = &#39;Weight Logger&#39;
 spr_client.ProgrammaticLogin()

        #Dict keys are the lowercase versions of your column headers
 dict = {}
 dict[&#39;date&#39;] = time.strftime(&#39;%m/%d/%Y&#39;)
 dict[&#39;time&#39;] = time.strftime(&#39;%H:%M:%S&#39;)
 dict[&#39;weight&#39;] = weight

 entry = spr_client.InsertRow(dict, spreadsheet_key, worksheet_id)
 if isinstance(entry, gdata.spreadsheet.SpreadsheetsList):
  print &quot;Insert row succeeded.&quot;
 else:
  print &quot;Insert row failed.&quot;

if __name__ == &quot;__main__&quot;:
 sys.exit(main())
&lt;/pre&gt;
&lt;br /&gt;
This code could easily be modified to achieve many different functions. For example, instead of entering any character to take your weight, it could be changed to take a name, so that multiple users can track their weights. Or maybe you want to set a timer so you don&#39;t have to hit a key on your keyboard to save your weight. The possibilities are endless.</content><link rel='replies' type='application/atom+xml' href='http://awestover.blogspot.com/feeds/2783474835369155772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awestover.blogspot.com/2012/03/wii-weights-internet-enabled-scale.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/2783474835369155772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/2783474835369155772'/><link rel='alternate' type='text/html' href='http://awestover.blogspot.com/2012/03/wii-weights-internet-enabled-scale.html' title='Wii Weights: An Internet Enabled Scale Using the Wii and Linux'/><author><name>Anthony Westover</name><uri>http://www.blogger.com/profile/18195411513816153742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2533571025684423868.post-6479721242825565620</id><published>2011-03-31T13:19:00.001-07:00</published><updated>2012-03-22T12:00:15.047-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="conditionals"/><category scheme="http://www.blogger.com/atom/ns#" term="elisp"/><category scheme="http://www.blogger.com/atom/ns#" term="emacs"/><category scheme="http://www.blogger.com/atom/ns#" term="file io"/><category scheme="http://www.blogger.com/atom/ns#" term="Perl"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="unix"/><title type='text'>Perls of Wisdom</title><content type='html'>Playing around some more with Perl I would like to share a few gems that I have discovered. This first comment will only impact any of a small number or users, but if you are programming on a *nix system using Emacs as your text editor you can use a little script to make the shebang appear in all of your perl files. Open up your .emacs file and insert the following code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;(setq auto-insert-directory (expand-file-name &quot;/home/awestove/mytemplates/&quot;\
))
    (setq auto-insert-query nil)
    (define-auto-insert &quot;\\.pl\\&#39;&quot; &quot;autoinsert.pl&quot;)
    (add-hook &#39;find-file-hooks &#39;auto-insert)
&lt;/pre&gt;&lt;br /&gt;
Basically what this is is elisp (emacs lisp) that sets up an auto-insert command. Every time you create a file with the .pl extension in emacs it will automatically insert the contents of autoinsert.pl into the file. Create the directory that you point to in the first line, and in that directory create your autoinsert.pl file. Inside of autoinsert.pl put your shebang (&quot;#! /usr/bin/perl&quot;) and anything else you want in every perl file you create. &lt;br /&gt;
&lt;br /&gt;
Sure this only saves a few keystrokes, but most programmers I know are quite lazy. I also created an alias:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;alias ep &quot;emacs /home/awestove/perl/\!*.pl&quot;
&lt;/pre&gt;&lt;br /&gt;
This short alias means that all I have to type is &quot;ep name&quot; and emacs will open a file name.pl in my perl subdirectory with the shebang on the first line. The joys of automation.&lt;br /&gt;
&lt;br /&gt;
Working some more with Perl I decided the next thing I wanted to focus on was some file I/O and conditional statements. Always good skills to have when learning any programming language, and Perl is no exception. All the better that Perl really simplifies the process of file I/O compared to other programming languages. The command is simply:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: pl&quot;&gt;open(FILEHANDLE, &quot;fileVariable&quot;);&lt;/pre&gt;&lt;br /&gt;
When you want to access the file you use the FILEHANDLE. If you want to open the file for reading place a &#39;&lt;&#39; before the file name, and use &#39;&gt;&#39; for writing. There are a lot of ways you can use this, so I&#39;ll just start with the sample program I made to play with some file I/O:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: pl&quot;&gt;#! C:/Perl/bin/perl
# ask the user to type the file name to read from
print &quot;What file am I reading?&quot;;
my $fileIn = &lt;&gt;;
chomp($fileIn);
# and the file name to write to
print &quot;What file should I create to write to?&quot;;
my $fileOut = &lt;&gt;;
chomp($fileOut);
# try to open the reading file, $opened is a boolean to signify if the operation was successful
my $opened = open(IN, &quot;&lt;$fileIn&quot;);
# unless is sort of an &#39;if not&#39; statement, unless the file opened, print an error and exit
unless($opened){
     print &quot;I could not open $fileIn&quot;;
     exit 1;
}
# if the file did open, try to open the output file
# instead of using an unless, we can just tell it to open &#39;or die&#39;
# dying prints the given message and exits
open(OUT, &quot;&gt;$fileOut&quot;) or die(&quot;I could not create $fileOut&quot;);
# using the &lt;&gt; command on a specific file handle gets input from that file, instead of the default STDIN
# while loop continues executing as long as something is true, once the last line is read the loop will end
while($line = &lt;in&gt;){
     # get rid of the new line
     chomp($line);
     # a reg exp, if the line contains the number 1, print it to the screen
     if($line =~ /1/){
          print &quot;$line\n&quot;;
     }
}
# the loop left us at the end of the file, we need to reopen to get back to the top
open(IN, &quot;&lt;$fileIn&quot;);
# @ means array, this reads the entire file into an array, one line per element
my @lines = &lt;in&gt;;
# printing to a file handle the sorted array
print OUT sort(@lines);
# closing our file connections
close(OUT);
close(IN);&lt;/pre&gt;&lt;br /&gt;
Note the sort function for arrays, this assumes by default the array is characters, so it sorts based on strings. That is to say if your file was:&lt;br /&gt;
&lt;br /&gt;
1&lt;br /&gt;
2&lt;br /&gt;
3&lt;br /&gt;
10&lt;br /&gt;
20&lt;br /&gt;
30&lt;br /&gt;
&lt;br /&gt;
It would be sorted to:&lt;br /&gt;
&lt;br /&gt;
1&lt;br /&gt;
10&lt;br /&gt;
2&lt;br /&gt;
20&lt;br /&gt;
3&lt;br /&gt;
30&lt;br /&gt;
&lt;br /&gt;
All in all the use of file I/O and regular expressions is very simple and powerful with Perl. There is a reason the language is still popular for certain scripting projects.</content><link rel='replies' type='application/atom+xml' href='http://awestover.blogspot.com/feeds/6479721242825565620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awestover.blogspot.com/2011/03/perls-of-wisdom.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/6479721242825565620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/6479721242825565620'/><link rel='alternate' type='text/html' href='http://awestover.blogspot.com/2011/03/perls-of-wisdom.html' title='Perls of Wisdom'/><author><name>Anthony Westover</name><uri>http://www.blogger.com/profile/18195411513816153742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2533571025684423868.post-6488137127737336865</id><published>2011-03-28T13:24:00.001-07:00</published><updated>2012-03-22T12:04:57.214-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Perl"/><category scheme="http://www.blogger.com/atom/ns#" term="unix"/><title type='text'>Learning Perl</title><content type='html'>Have you ever woken up and said, &quot;Today would be a great day to learn a new programming language?&quot; Today is one of those days and I have decided on learning Perl. Why Perl? Why not! Perl is an older language but still being developed and maintained, and is a dynamic language. Perl supports many different programming paradigms and is particularly powerful for tasks such as text parsing and code generation. For small scripts it is nice to have a basic language that you can just hack out some commands and get the job done, and Perl is an excellent choice for doing that. I am sure Perl has many more uses, but I am just learning it along with you right now, so we will discover those other uses when the time comes.&lt;br /&gt;
&lt;br /&gt;
If you are working on a Macintosh or *nix system, chances are Perl is already installed, but for Windows users you will need to download and install it. I personally recommend ActivePerl which you can download from &lt;a href=&quot;http://www.activestate.com/activeperl/downloads&quot;&gt;here&lt;/a&gt;. Just download the most recent version for your operating system and follow the instructions. When installing, make sure you check the option to add Perl to the Windows PATH variable.&lt;br /&gt;
&lt;br /&gt;
With Perl installed it is best to follow tradition and start with a Hello World program. Using your text editor of choice create a blank document. The first line in all Perl programs is called &lt;emphasize&gt;shebang&lt;/emphasize&gt; and should be something like:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;#! usr/bin/perl for *nix
or #! C:/Perl/bin/perl for Windows&lt;/pre&gt;&lt;br /&gt;
Since Perl is interpreted rather than compiled, this shebang points to the Perl interpreter. The rest of the code in the file is sent to the interpreter where it is run. In this program, we are only interested in doing one simple thing, printed a phrase to the screen, also know as standard output. To do this in Perl, like many other languages, the command is simply &lt;emphasize&gt;print&lt;/emphasize&gt; followed by the string we want to print, using quotations for literals. So for our hello world program the full code is:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: pl&quot;&gt;#! C:/Perl/bin/perl
print &quot;Hello World!\n&quot;;&lt;/pre&gt;&lt;br /&gt;
Nice and simple. Make sure you note the semicolon at the end of the print command and the lack of the semicolon after the shebang. This is because the shebang is not an actual Perl command, but rather a scripted instruction to the interpreter. Now, this is all well and good, but not overly useful, so let&#39;s add a few new things to our program. Some of the most useful things in a programming language are variables and input, so let&#39;s add those two features.&lt;br /&gt;
&lt;br /&gt;
Instead of saying hello to the whole world, let&#39;s get personal and say hello just to the person running the program. In order to do this, we are going to have to ask there name using standard input. In Perl standard input is signified by &amp;lt;stdin&amp;gt; but by convention can be shortened to &amp;lt;&amp;gt;. To provide a prompt just use the print command. In order to save the answer the user gives us, however, we will need to create a variable, which in Perl is signified by a dollar sign ($). So, to ask the user their name and store it in a variable we would type:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: pl&quot;&gt;print &quot;What&#39;s your name?&quot;;
$name = &amp;lt;&amp;gt;;
print &quot;Hello $name!&quot;;&lt;/pre&gt;&lt;br /&gt;
Note that their is no need to concatenate the variable into the string literal, the use of the $ tells the interpreter that you want the value of the variable, not a literal $, to be printed to the screen. If you tried actually running this code, you might notice that the formatting seems off, specifically the program prints out a new line after the name before the exclamation point. This is because when the user typed their name, they hit the &#39;Enter&#39; or &#39;Return&#39; key, and that new line got saved in the variable as well. To remove this new line we can use &lt;emphasize&gt;chomp&lt;/emphasize&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: pl&quot;&gt;chomp($name);&lt;/pre&gt;&lt;br /&gt;
Notice that you do not need to do $name = chomp($name); chomp actually modifies the passed in variable directly. With all of this our final program should look like:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: pl&quot;&gt;#! C:/Perl/bin/perl
print &quot;What&#39;s your name?&quot;;
$name = &lt;&gt;;
chomp($name);
print &quot;Hello $name!&quot;;&lt;/pre&gt;&lt;br /&gt;
And now we have a basic understanding of starting Perl. If you notice that the DOS window closes automatically without letting you see the program, either run the program from the command line, or add an extra &lt;&gt;; as the last line. This will stop the program from completing until you hit enter.</content><link rel='replies' type='application/atom+xml' href='http://awestover.blogspot.com/feeds/6488137127737336865/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awestover.blogspot.com/2011/03/learning-perl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/6488137127737336865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/6488137127737336865'/><link rel='alternate' type='text/html' href='http://awestover.blogspot.com/2011/03/learning-perl.html' title='Learning Perl'/><author><name>Anthony Westover</name><uri>http://www.blogger.com/profile/18195411513816153742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2533571025684423868.post-204036630321935560</id><published>2011-01-24T20:41:00.001-08:00</published><updated>2012-03-22T12:09:03.508-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="gui"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jbutton"/><category scheme="http://www.blogger.com/atom/ns#" term="jframe"/><category scheme="http://www.blogger.com/atom/ns#" term="jpanel"/><category scheme="http://www.blogger.com/atom/ns#" term="minesweeper"/><title type='text'>Minesweeper in Java: Part One - GUI</title><content type='html'>Continuing from yesterdays post about Minesweeper as an introduction to game programming today we are going to start by creating Minesweeper in Java, a traditional starting language. Creating graphical user interfaces is normally more advanced of a topic than a usual starting tutorial, but the basics are quite simple. &lt;br /&gt;
&lt;br /&gt;
For Minesweeper the basic interface for the game is a simple grid with squares. In Java we will do this by creating a JPanel with GridLayout. For simplicity sake we will assume that the grid will always be 10x10. These are set in the constructor.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;import java.awt.*;
import javax.swing.*;

public class GameGridGui extends JPanel{

public GameGridGui(){
     this.setSize(400,400);
     this.setLayout(new GridLayout(10,10));
}
}&lt;/pre&gt;&lt;br /&gt;
Once the basic layout is taken care of the next thing that needs to be done is build the squares. There are lots of ways to do this but since we need to click on the squares there is no reason why we shouldn&#39;t just use an array of JButtons. Create a method called buildButtons and call it from your constructor.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;import java.awt.GridLayout;

import javax.swing.JButton;
import javax.swing.JPanel;

public class GameGridGui extends JPanel{

 private JButton squares[][];
 
public GameGridGui(){
     this.setSize(400,400);
     this.setLayout(new GridLayout(10,10));
     squares = new JButton[10][10];
     buildButtons();
}

private void buildButtons(){
     for(int i=0;i&amp;lt;10;i++){
          for(int j=0;j&amp;lt;10;j++){
               squares[i][j] = new JButton();
               squares[i][j].setSize(400,400);
               this.add(squares[i][j]);
          }
     }
}
}&lt;/pre&gt;&lt;br /&gt;
If you want to test this out to see what it looks like, just create a quick main method with a JFrame.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;public static void main(String[] args) {
  GameGridGui g = new GameGridGui();
  JFrame frame = new JFrame(&quot;My Minesweeper&quot;);
  frame.add(g);
  frame.setSize(400,400);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true);
 }
&lt;/pre&gt;&lt;br /&gt;
And with that you have a basic Minesweeper GUI in Java.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVSG2vERohaDPOcAgcSJWh_I2OOPCQ77osQY2GgspGRDXJoYNJYgnH3PRpI6GY8L_5ZNJry9pnhX1Bcyz2KZnM7nfeX-FGMbjtykf82soB-MHLBu8Qa4670XXav3Rd2VushX-y8lcFNyw/s1600/minesweeper.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; width=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVSG2vERohaDPOcAgcSJWh_I2OOPCQ77osQY2GgspGRDXJoYNJYgnH3PRpI6GY8L_5ZNJry9pnhX1Bcyz2KZnM7nfeX-FGMbjtykf82soB-MHLBu8Qa4670XXav3Rd2VushX-y8lcFNyw/s320/minesweeper.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://awestover.blogspot.com/feeds/204036630321935560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awestover.blogspot.com/2011/01/minesweeper-in-java-part-one-gui.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/204036630321935560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/204036630321935560'/><link rel='alternate' type='text/html' href='http://awestover.blogspot.com/2011/01/minesweeper-in-java-part-one-gui.html' title='Minesweeper in Java: Part One - GUI'/><author><name>Anthony Westover</name><uri>http://www.blogger.com/profile/18195411513816153742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVSG2vERohaDPOcAgcSJWh_I2OOPCQ77osQY2GgspGRDXJoYNJYgnH3PRpI6GY8L_5ZNJry9pnhX1Bcyz2KZnM7nfeX-FGMbjtykf82soB-MHLBu8Qa4670XXav3Rd2VushX-y8lcFNyw/s72-c/minesweeper.png" height="72" width="72"/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2533571025684423868.post-5933281868068654768</id><published>2011-01-23T21:31:00.000-08:00</published><updated>2011-01-23T21:31:12.135-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="computer"/><category scheme="http://www.blogger.com/atom/ns#" term="game"/><category scheme="http://www.blogger.com/atom/ns#" term="minesweeper"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="programming language"/><title type='text'>A Mine in Many Languages</title><content type='html'>One of my favorite games is the Windows classic Minesweeper. It is a simple yet addictive game that really engages your mind, and it is an excellent introduction to game programming. A lot of budding programmers are most interested in game programming because it gives you instant gratification, the visible results and interactivity that is missing from a large number of introductory programming assignments. Minesweeper may not have the flashy graphics or multiplayer capabilities of a hit game, but it is that simplicity that makes it an excellent starting program.&lt;br /&gt;
&lt;br /&gt;
With any program, no matter the language or the scale, the first thing that you want to do is determine what exactly you will need. For minesweeper the list is fairly straightforward:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Area to display the grid.&lt;/li&gt;
&lt;li&gt;Ability to click on squares in the grid.&lt;/li&gt;
&lt;li&gt;Ability to distinguish between unclicked square, square with a mine, square with a number, and square that has been flagged.&lt;/li&gt;
&lt;li&gt;On square click, the ability to determine if the square is a mine and if not the ability to count neighboring squares.&lt;/li&gt;
&lt;li&gt;Ability to detect when game is finished, either by clicking on a mine or by clicking on all non-mine squares.&lt;/li&gt;
&lt;li&gt;(Optional) Timer or move counter&lt;/li&gt;
&lt;li&gt;(Optional) Ability to change options; grid size, number of mines, etc.&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
Your answer to these questions may change depending on the language you choose to write the program in, and the personal desires of the client. It is important to note that creating any list such as this is not meant to be too detailed or all inclusive. Some programmers prefer to just jump right in, others prefer to have absolutely everything planned and outlined in advance. &lt;br /&gt;
&lt;br /&gt;
I will be referring back to this post regularly, with the goal of having a working version of minesweeper in every language that I learn.</content><link rel='replies' type='application/atom+xml' href='http://awestover.blogspot.com/feeds/5933281868068654768/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awestover.blogspot.com/2011/01/mine-in-many-languages.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/5933281868068654768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/5933281868068654768'/><link rel='alternate' type='text/html' href='http://awestover.blogspot.com/2011/01/mine-in-many-languages.html' title='A Mine in Many Languages'/><author><name>Anthony Westover</name><uri>http://www.blogger.com/profile/18195411513816153742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2533571025684423868.post-2532061300943910489</id><published>2011-01-20T20:42:00.001-08:00</published><updated>2012-03-22T12:12:50.796-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ascii"/><category scheme="http://www.blogger.com/atom/ns#" term="Brainfuck"/><category scheme="http://www.blogger.com/atom/ns#" term="Esoteric"/><category scheme="http://www.blogger.com/atom/ns#" term="hello world"/><category scheme="http://www.blogger.com/atom/ns#" term="Lolcats"/><category scheme="http://www.blogger.com/atom/ns#" term="Lolcode"/><category scheme="http://www.blogger.com/atom/ns#" term="programming language"/><title type='text'>Esoteric is as Esoteric does</title><content type='html'>There is a whole realm of esoteric programming languages, languages which really serve no purpose other than existing. One example is lolcode, the programming language of lolcats. A quick example program in lolcode looks like:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;HAI
CAN HAS STDIO?
VISIBLE &quot;HAI WORLD!&quot;
KTHXBYE&lt;/pre&gt;&lt;br /&gt;
This code is nothing more than hello world, &quot;HAI&quot; and &quot;KTHXBYE&quot; represent the open and close blocks, CAN HAS is the equivalent of an import or include statement, with STDIO being the namespace for standard input and output. Finally VISIBLE is the command to print out to the screen, followed by the string literal &quot;HAI WORLD!&quot;, which is what would be printed out to the screen.&lt;br /&gt;
&lt;br /&gt;
Of course, lolcode is not the only esoteric programming language out there. Another esoteric language is the aptly named Brainfuck. Learning this language will fry your mind worse than any night binging on whiskey and vodka. Once again we are going to start out with the simplest program, hello world.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;++++++++++
[&amp;gt;+++++++&amp;gt;++++++++++&amp;gt;+++&amp;gt;+&amp;lt;&amp;lt;&amp;lt;&amp;lt;-]
&amp;gt;++.&amp;gt;+.+++++++..+++.&amp;gt;++.
&amp;lt;&amp;lt;+++++++++++++++.
&amp;gt;.+++.------.--------.&amp;gt;+.&amp;gt;.
&lt;/pre&gt;&lt;br /&gt;
Right now you are probably saying &quot;What the fu...&quot;, but what you should be saying is &quot;What the brainfu...&quot; Brainfuck uses only 8 symbols and runs using a set of counters. In this example there are 5 elements in an array, &#39;&amp;lt;&#39; and &#39;&amp;gt;&#39; iterate through the array, &#39;+&#39; and &#39;-&#39; increment and decrement the values respectively, &#39;[&#39; and &#39;]&#39; denotes a loop and &#39;.&#39; prints to the screen. So to start with the array[1] is set to 10, this is the constraints for the loop. The loop then iterates 10 times (notice the - at the end of the loop when the pointer has returned to the first element) Since this happens 10 times array[2] becomes 70, array[3] becomes 100, array[4] becomes 30 and array[5] becomes 10.&lt;br /&gt;
&lt;br /&gt;
With these values the letters can start to be printed. Array[2] becomes 72 and is printed out, 72 being the ascii value for &#39;H&#39;. Next 101 is printed (&#39;e&#39;), 108 (&#39;l&#39;) is printed twice, and so on, using &amp;lt; &amp;gt; + and - to change the ascii values that are printed.&lt;br /&gt;
&lt;br /&gt;
These are far from being the only esoteric languages out there, but they manage to show a good glimpse at what you can expect from extremely bored programmers.</content><link rel='replies' type='application/atom+xml' href='http://awestover.blogspot.com/feeds/2532061300943910489/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awestover.blogspot.com/2011/01/esoteric-is-as-esoteric-does.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/2532061300943910489'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/2532061300943910489'/><link rel='alternate' type='text/html' href='http://awestover.blogspot.com/2011/01/esoteric-is-as-esoteric-does.html' title='Esoteric is as Esoteric does'/><author><name>Anthony Westover</name><uri>http://www.blogger.com/profile/18195411513816153742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2533571025684423868.post-1829897607469837626</id><published>2011-01-19T19:09:00.001-08:00</published><updated>2012-03-22T12:14:54.967-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Chrome"/><category scheme="http://www.blogger.com/atom/ns#" term="CSS"/><category scheme="http://www.blogger.com/atom/ns#" term="Doctype"/><category scheme="http://www.blogger.com/atom/ns#" term="Firefox"/><category scheme="http://www.blogger.com/atom/ns#" term="HTML"/><category scheme="http://www.blogger.com/atom/ns#" term="Internet Explorer"/><category scheme="http://www.blogger.com/atom/ns#" term="XHTML"/><title type='text'>Misadventures in CSS</title><content type='html'>&lt;table&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td class=&quot;smallfont&quot;&gt;&lt;div style=&quot;margin: 5px 20px 20px;&quot;&gt;So I have spent the past two days updating various websites to make sure they looked nice and worked in all the various browsers, specifically Chrome, Firefox, and IE 8. As anybody who has spent any time at all working on CSS can tell you, programming for Firefox and Chrome is simple, Internet Explorer... not so much. There are several nuances that make Internet Explorer difficult, they have gotten better with IE 8 - I remember having to create entirely different CSS files, one for IE and one for other browsers - but as my headaches these past days can attest to, cross compliance is far from reality.&lt;/div&gt;&lt;div style=&quot;margin: 5px 20px 20px;&quot;&gt;One specific issue I was having was formatting select elements, the drop down boxes with pre-populated values that are so common on HTML forms. Specifically, my client needed added space between three elements, a date field, month field, and year field. Chrome automatically added in some space, but Internet Explorer and Firefox mashed all three fields together. &quot;No problem,&quot; I thought to myself, &quot;one quick CSS rule and I&#39;ll be on my way.&quot;&lt;/div&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: css&quot;&gt;select{
     margin-right: 0.5em;
}&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;div style=&quot;margin: 5px 20px 20px;&quot;&gt;A quick refresh and Firefox confirmed that this rule worked as expected, but alas, Internet Explorer did not want to play ball. Now, when updating a website lots of things could be the problem: is the CSS code even being reached? Is there a cached version still being used? Is there an error with the CSS? With the HTML? Using a hard-refresh (control-F5) to clear cache, and using Developer Tools to trace the CSS, I ruled out the first two possibilities, and since the code worked perfectly in Firefox and Chrome, one would think the other two were equally impossible. After a little tweaking I found the silly little bug, Internet Explorer cannot or will not style a select element without also styling the option element, the various dropdown options that appear when you click on the box. With that the working code for all three browsers is:&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: css&quot;&gt;select{
     margin-right: 0.5em;
} 

option{
     margin-right: 0.5em;
} &lt;/pre&gt;&lt;br /&gt;
&lt;div style=&quot;margin: 5px 20px 20px;&quot;&gt;The other issue I had the pleasure of tangling with was getting an entire form to be centered on the page while keeping the elements left aligned with one another. Once again the fix for Firefox and Chrome was quite simple:&lt;/div&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: css&quot;&gt;form{
     margin: 0 auto;
}&lt;/pre&gt;&lt;br /&gt;
&lt;div style=&quot;margin: 5px 20px 20px;&quot;&gt;The shorthand for the margin command sets the top and bottom margins with the first value, and the left and right with the second. Since the left and right margins are both set to the same auto-computed value, the content becomes horizontally centered on the page. Of course, Internet Explorer chooses to ignore this command by default. This fix is deceptively simple though, and many programmers will not even notice the issue. The problem comes with Internet Explorer&#39;s Quirks mode, if a website does not specify an HTML Doctype, Internet Explorer defaults to an old, HTML 4 compliant version. To force an updated XHTML 1 rendering, place the following line at the VERY top of your webpage, even before the &amp;lt;html&amp;gt; tag.&lt;/div&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: css&quot;&gt;&amp;lt;!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;div style=&quot;margin: 5px 20px 20px;&quot;&gt;A simple fix to solve future headaches.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;</content><link rel='replies' type='application/atom+xml' href='http://awestover.blogspot.com/feeds/1829897607469837626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awestover.blogspot.com/2011/01/misadventures-in-css.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/1829897607469837626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/1829897607469837626'/><link rel='alternate' type='text/html' href='http://awestover.blogspot.com/2011/01/misadventures-in-css.html' title='Misadventures in CSS'/><author><name>Anthony Westover</name><uri>http://www.blogger.com/profile/18195411513816153742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2533571025684423868.post-3449217962183233216</id><published>2011-01-18T13:25:00.001-08:00</published><updated>2011-01-18T13:56:43.798-08:00</updated><title type='text'>The Start of a Journey</title><content type='html'>Hello all, I am Anthony Westover from Valparaiso University, and I am a computer programmer. If there is one thing I love about computer programming it is learning and using as many languages as possible. Each language is unique, each has a set of strengths and weaknesses. This is a journey through the universe of programming languages.</content><link rel='replies' type='application/atom+xml' href='http://awestover.blogspot.com/feeds/3449217962183233216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awestover.blogspot.com/2011/01/start-of-journey.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/3449217962183233216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2533571025684423868/posts/default/3449217962183233216'/><link rel='alternate' type='text/html' href='http://awestover.blogspot.com/2011/01/start-of-journey.html' title='The Start of a Journey'/><author><name>Anthony Westover</name><uri>http://www.blogger.com/profile/18195411513816153742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>