Showing posts with label classes. Show all posts
Showing posts with label classes. Show all posts

Friday, May 20, 2011

Your Own Java Classes

To use Java effectively, you want to create and use your own classes. This is one of the great powers of object-oriented languages--the ability to construct programs out of independent building-blocks that cut large problems down into small, easily solvable ones. There's a lot more that can be said, and much of it is elsewhere. So I'll get right into a very simple, very basic example here.

We're going to create a very simple object class that will print a "Hello" message to the screen when called. This class will have two different methods that will do the same thing, though we'll vary the messages they print a bit so that we can see which one is doing the work.

Here's our class: (download HelloClass.Java)

public class HelloClass{

/**
* sayHello() prints "Hello!" to the Java console output.
*/
public void sayHello(){
System.out.println("Hello!\n");
}

/**
* doHello() prints "Hello, hello!" to the Java console output.
* It's static, so you don't need to instatiate a HelloClass
* object to use it.
*/
public static void doHello(){
System.out.println("Hello, hello!\n");
}

} // End of HelloClass


The two methods we have to print messages are sayHello() and doHello(). To use sayHello(), we need to have a HelloClass object created, then call that object's sayHello() method.

doHello(), however, is a static method. This means is belongs to the class, not to any object of the class. So we can use it without any HelloClass objects being created first.

Here's a class that uses these methods as described: (download UseHello.java)

public class UseHello{
public static void main(String[] arg){

// We can use doHello() without a HelloClass object:
HelloClass.doHello(); // call the HelloClass's doHello() method.

// But we need to create a HelloClass object to use sayHello():
HelloClass hello=new HelloClass();
hello.sayHello(); // call hello's sayHello() method.

}
} // End of UseHello.


If we try to call sayHello() without first creating a HelloClass object, like this:
HelloClass.sayHello();

then we'll get the dreaded "calling a non-static method from a static context" error message. That's letting you know that you need to instantiate (or create) a HelloClass object first, then tell that object to call its method.

Static methods are useful for things like general arithmetic and calculation or other methods that might be used in a way where state information is unimportant. But beware, it's easy to create static methods when what's really wanted is an object that does what you want.

Files available for download through: http://saundby.com/beginwithjava/.
StumbleUpon

Tuesday, January 25, 2011

Java's File Names and Class Names

Java is picky about the file names you use.

Each source file can contain one public class. The source file's name has to be the name of that class. By convention, the source file uses a .java filename extension (a tail end of a file name that marks the file as being of a particular type of file.)

So, for a class declared as such:

public class HelloWorld{
...

The file it is stored in should be named HelloWorld.java.

The capitalization should be the same in both cases. Some operating systems don't notice whether file names are capitalized or not. It doesn't matter, you should be in the habit of using the correct capitalization in case you work on a system that does care about capitalization.

When you compile your file with javac, you pass the full file name to javac:

javac HelloWorld.java

Let's say we save the file under a different name. We write the following program:

public class HelloThere{
public static void main(String arg[]){
System.out.println("Hello There.");
}
}

Then we save it as HelloWorld.java, and try to compile it:

>javac HelloWorld.java
FileName.java:1: class HelloThere is public, should be declared
in a file named HelloThere.java
public class HelloThere{
^
1 error


Java lets us know that it won't compile until we rename the file appropriately (according to its rules.)

So let's rename the file. Let's call it HelloThere.javasource. Seems a bit more explicit than just .java, right? Let's run the compiler:


>javac HelloThere.javasource
error: Class names, 'HelloThere.javasource', are only accepted
if annotation processing is explicitly requested
1 error

Java's still not happy with us. Annotation processing? That's when we include extra information in the program about the program itself. We're not bothering with that just now. So we should just name the file HelloThere.java, and not get fancy with our file names.

But, under the right circumstances, javac does allow file name extensions other than .java. That's why we always type in the full file name, including .java, when we use javac. We say 'javac HelloThere.java', not just 'javac HelloThere'. Javac can't assume that we mean a .java file, though that's what it will usually be.

The Class File

Once we make javac happy with a proper file name, and a program with no errors, javac produces a new file. This file will have the original file name, but with .java replaced with .class. This is your bytecode file, the file that the Java Virtual Machine can run.

When we run the program with Java, we're running the .class file. In the case of HelloThere, we're running the HelloThere.class file. But we don't type in the full file name. Why?

Unlike javac, java requires a .class file. That's all it will work with. There's no opportunity to have a different extension to the file name. So it assumes the .class part of the file name. But that's not the whole story.

If you add .class yourself, here's what you'll get:

>java HelloThere.class
Exception in thread "main" java.lang.NoClassDefFoundError:
HelloThere/class
Caused by: java.lang.ClassNotFoundException: HelloThere.class
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

Pretty ugly. What we're actually doing when we type "java HelloThere" is telling Java to run the class HelloThere. Java assumes that it will find this in a file called "HelloThere.class", so that's what it's looking for first.

We're not telling Java to run the file HelloThere.class, we're telling it to run the class HelloThere, which it expects to find in the file HelloThere.class.

But what if we ask for another class that doesn't have its own .class file?

Just for fun, let's change HelloThere.java like this, and see what happens:
public class HelloThere{
public static void main(String[] arg){
System.out.println("Hello.");
}
}

class HelloZoik{
public static void main(String[] arg){
System.out.println("Zoiks!");
}
}

After we edit it, we compile with 'javac HelloThere.java' and hold our breath.

Hurray! No errors!

Now we have a second class, HelloZoik, in the HelloThere.class file. Can Java find it?

Let's try:
 java HelloZoik
Zoiks!

It worked! Java found our class inside HelloThere.class.

This shows it's not the file name that we're calling with the 'java' command, it's the class name.

If Java doesn't find the class inside a file with the same name as the class followed by .class, it'll look in the other .class files available.
StumbleUpon

Tuesday, August 24, 2010

Using Game Controllers with Java

In the past, I've covered using mice as input devices, and covered the general input mechanism of Listeners. I've also discussed keyboard input for console applications, and I'll soon be covering Key Bindings as a way of using the keyboard in GUI applications.

But there's no facility in Java itself that deals with game pads easily. To date, it's been necessary to create your own ActionListeners from scratch. But not any more. Thanks to the JInput project, there's an easier way to hook up game controllers to your software.

JInput attempts to do discovery on your game controller, to figure out what its setting are, what buttons and controls it has, what the center positions are of analog sticks, and so on. All that messy stuff that makes rolling your own so darn painful. It's not 100% universal, but for most controllers and most games, it will do the job admirably. If you want better for a specific controller of your own, you can extend the classes to handle your stick (and maybe feed that information back to the JInput team so that they can decide whether to include it in future releases.

It's multi-platform, Windows, Mac OS X, and Linux. So it doesn't have the limitations of a lot of the other gamepad code implementations that use native code, thus limiting themselves to one platform (usually Windows.)

If you want to see an implementation using JInput, check out Greenfoot with Gamepads. It's a good, clear example of using JInput in a general fashion.
StumbleUpon

Wednesday, August 11, 2010

Java's Inner Classes: The Keys to the Kingdom

In my two most recent code examples I've used inner classes in the program.

Java Video Game Programming: Game Logic

A Simple Java Video Game Kernel

An inner class is a Java class that's defined inside another class. In both the examples above, I have a class called VGKernel, which is the class that implements the video game kernel. Inside that class, I define other classes. This has a special effect on the relationship between those classes and VGKernel.

Normally, our objects are encapsulated, that is, their members (variables and methods) are inaccessible to other classes unless they've been marked as public, and in those cases we take care to make sure that the object can't be messed up using those public members.

Some things in Java don't work very well with the encapsulation. Graphics and Threads are two of them. Fortunately, there's a way around the encapsulation. It lets one object access all the members of another object as if it owned them.

The downside is that this can be a dangerous coding practice, like global variables (check out the sort of problems  JavaScript's had with security, if you want to know why global variables are a problem.) Your inner class has complete control over the outer class. Root access, keys to the kingdom. It could wear the outer class like the alien guy wore the redneck's skin in Men in Black.

If used well inner classes solve a multitude of problems. In the case of the two versions of VGKernel, it solves the problem of the ball being able to access the graphical context (at present, the Ball class doesn't really need to, I'll admit, but we'll see more of why it does this as the code develops in future articles), and it allows VGTimerTask to access the methods of VGKernel.

The Java Tutorial has a pretty good section on inner classes, as one type of nested class.
StumbleUpon

Monday, August 9, 2010

Java Video Game Programming: Game Logic

The simple video game kernel I presented earlier is a good start, but some compromises were made to make it as simple as possible. Now we're going to start adding back some of the complexity to give us more control over what we can do with it.

The first step is to make the game's ball a real object, rather than some variables within our JFrame.

In simple video games, there is usually some object in the game that does most of the "thinking" with respect to the game's rules. In a game like Pong or Breakout, the ball does most of the "thinking". The paddles move according to user input, but they don't really need to know if they've collided with anything in the game (their own logic keeps them from moving off the playfield.) The bricks don't need to know anything about what's going on, they just need to hang around, then disappear when something tells them to, and perhaps return some information about what score they're worth, if there are different scores for hitting different bricks.

The ball, however, is a more active participant in the game. It needs to know about collisions, respond to the other objects in the game, and generally know what's going on. In other words, it is the object that keeps track of most of the game rules. In a video game, this is referred to as the game logic.


A bouncing ball in the simple Java video game kernel program.

This simple kernel improves on the original. Turn it into your own Pong, Breakout, or Tank clone.

In the example below I've made a Ball class. This is where most of the game's logic will reside. Here it is in the ball's move() method. Since the ball will need access to inside information about the playfield and the objects on it, I've made it an inner class of the playfield's class (VGKernel.) As an inner class, it has access to all of VGKernel's members and methods as if it owned them itself. This simplifies the program a lot.

Here is the modified version of the video game kernel. Changes from the original have been highlighted:
/* A simple video game style kernel, revision 2.
   by Mark Graybill, August 2010
   Uses an inner class to contain game logic,
   with another inner class as a game timer.
*/

// Import Timer and other useful stuff:
import java.util.*;
// Import the basic graphics classes.
import java.awt.*;
import javax.swing.*;
import java.lang.Math;

public class VGKernel extends JPanel{

// This is not a recommended coding practice, just a shortcut.
public Rectangle screen, bounds; // The screen area and boundary.
public JFrame frame; // A JFrame to put the graphics into.
public VGTimerTask vgTask; // The TimerTask that runs the game.
public VGBall ball; // The game ball.
// Create a constructor method:
  public VGKernel(){
    super();
    screen = new Rectangle(0, 0, 600, 400);
    bounds = new Rectangle(0, 0, 600, 400); // Give some temporary values.
    ball = new VGBall();
    frame = new JFrame("VGKernel");
    vgTask = new VGTimerTask();
}

  // Create an inner TimerTask class that has access to the
  // members of the VGKernel.
  class VGTimerTask extends TimerTask{
    public void run(){
      ball.move();
      frame.repaint();
    }
  }

  // Create an inner VGBall class that has our game logic in it.
  class VGBall{
    // Accessor methods would be more proper,
    // but for now I just make the needed variables public.
    public int x, y, width, height; // Ball's location and size.
    int xVel, yVel; // The ball's velocity.

    public VGBall(){
      x = 0;
      y = 0;
      width = 20;
      height = 20;
      xVel = width/4;
      yVel = height/4;
    }
    // Instance methods for VGBall
    public void move(){
      // Move the ball according to the game rules.
      x+=xVel; // Move horizontally.
      y+=yVel; // Move vertically.
      // Detect edges and bounce if necessary.
      if (x > (bounds.width - width)){
        xVel = -xVel; // reverse movement.
        x = bounds.width -  width; // Set location to screen edge.
      }
      if (y > (bounds.height - height)){
        yVel = -yVel; // reverse movement.
        y = bounds.height - height;
      }
      if (x <= 0) { xVel = -xVel; x = 0; }
      if (y <= 0) { yVel = -yVel; y = 0; }
    }
  } // end of class VGBall

// Now the instance methods:
  public void paintComponent(Graphics g){
    // Get the drawing area bounds for game logic.
    bounds = g.getClipBounds();
    // Clear the drawing area, then draw the ball.
    g.clearRect(screen.x, screen.y, screen.width, screen.height);
    g.fillRect(ball.x, ball.y, ball.width, ball.height);
  }

  public static void main(String arg[]){

    java.util.Timer vgTimer = new java.util.Timer();  // Create a Timer object
    VGKernel panel = new VGKernel(); 
    
    panel.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    panel.frame.setSize(panel.screen.width, panel.screen.height);

    panel.frame.setContentPane(panel); 
    panel.frame.setVisible(true);

    // Set up a timer to do the vgTask regularly.
    vgTimer.schedule(panel.vgTask, 0, 33);
  }
}
Now the ball not only is its own class, it has a more sophisticated means of keeping track of its direction of movement (xVel and yVel, tracking velocity as a positive or negative value, as opposed to the simple right and down booleans in the original.) This means that logic in the game could vary the velocity of the ball easily, as well as change its direction of movement.

Other objects on the playfield should be defined in their own classes, outside VGKernel. This will keep VGKernel from becoming too long and from making the program too monolithic and difficult to maintain.

Simple exercises:
Since the ball has access to VGKernel's members, including the drawing screen, the ball can be made to draw itself. By giving the ball its own draw() method, we can make it easier to change the appearance of the ball at will. Give it a try.
StumbleUpon

Tuesday, April 13, 2010

The List in Java

A Java List is a way for keeping track of things in the order you put them in. They are part of the Collections framework in Java, in other words, they are a kind on Collection. Collections all share some abilities, and can easily be converted from one kind of Collection to another.

List is an Interface, which means that it is not a Class, but a standard that you can make a class adhere to. By making a class a List, and implementing at least the required methods of a List, you have the abilities of a List, as if it were a class.
Make sure you have the right List when you look it up.
This is the one you want. The List class from the java.awt package is something different.


Lists are used to keep a list of objects. This seems obvious, but there are lots of ways of collecting up a number of objects in Java, including sets, arrays, different types of lists like linked lists, and maps. Each has its own characteristics. A List is good for sets of objects where you don't know how many objects there might be, where you want the objects kept in the order you put them in, and where you want to be able add objects to the list or remove them. Objects can be added to or removed from Lists en masse. Lists can also be tested against other collections to see if they include all the objects in that list, or none of them.
  • Lists start at zero and go up to the number of objects in them, minus one.

  • You can determine if a List is empty (true or false) using isEmpty()

  • You can get the size of a List using size()

  • You can access an item in a List by its index using get().

  • Items can be added to the end of a List with add(), or

  • You can insert an object into a particular place in a List, moving the rest "down" with add(index, element).

  • You can put one object repeatedly in a List (unlike a Set).

  • You can find the first instance of an object in a List (getting its index) with indexOf(), or

  • You can get the last instance of an object (getting its index) with lastIndexOf()

  • You can delete an object from a List with remove().

  • You can append all the members of some other Collection to a List at once with addAll().

  • You can delete all members of some other Collection from a List all at once with removeAll().

  • You can delete all members that are not in another Collection with retainAll()

  • You can see if all members of a Collection are present in a List with containsAll().

  • You can clear the list out with clear()

  • or keep a section of it with subList().

Some things you can do with a List.

See Lists in Java: Sample Code for examples of using a List.

Many programmers first encounter the List when they run into a method for something they're working with that returns a List. If you're not used to using Collections, this will seem to add an extra layer of complexity. However, it lets the method deal with giving you a group of objects as its return value, without it having to know how many things it might be returning in advance, or what the classes of those objects will be.

For example, the Greenfoot framework for Java makes copious use of the List. If you have a World in Greenfoot that contains a bunch of Robot objects, like this:
A World That Contains a Bunch of Robots

You can do something to all the Robots by calling a World method that returns a List of the Robots.

Using the List


Once you've got the List, you can then do something to all the Robots by iterating through the list and calling the appropriate method for each Robot. To do this, we use the List's ability to provide us with an iterator to move between its elements one by one once we get the List. In this case, it's done automatically by Java's for-each loop:
List<robot> robots = getWorld().getObjects(Robot.class); // get a List of Robots

for (Robot thisRobot : robots) {
thisRobot.turnLeft();
}

This goes through and calls the turnLeft() method of each robot returned in the list.

To explicitly get an iterator from a List, we can use the listIterator() method of the List:
ListIterator robotIterator = robots.listIterator();

This gives us a list iterator that starts at zero and progresses through the list as we call the iterator's next() method, after checking to see that there is a next item using hasNext(), of course. See ListIterator to see what you can do with the iterator.

We can also get an iterator that starts at a particular position in the list. For example, let's say we want to skip our way past the first 100 elements:
ListIterator robotIterator = robots.listIterator(100);


The normal use of a List is as a simple list of objects to iterate through, as shown. The use of the additional features of the List make it a far more powerful construct, however. In general, it's very useful to learn as much about Collections in Java as possible, as they are the most generally useful data structures for dealing with groups of objects.

See Lists in Java: Sample Code for examples of using a List.
StumbleUpon

Friday, February 20, 2009

Rotating an Image with Java

In an earlier lesson we learned to load an image file into Java and display it. We also scaled the image in the program given in that lesson. Now we're going to get just a tiny bit more sophisticated, and rotate the image, as promised in the lesson introducing Java2D.

The basic graphics functions of Java allow for positioning an image in a window and scaling that image. But that's about all. If you want to rotate the image, skew it (make it look like it's leaning over) or do other things to the image you display you need to use Java2D.

What we'll do in this program is load the image as before. But before the image is drawn we will create a Java2D version of our graphics object that we're drawing to. Then we'll rotate that graphics object and draw the image. The rotation results in everything that gets drawn to the graphics area being rotated by the amount specified.

The program uses the same image of Duke as the previous one. It needs to be in the same directory as your program.

Here's the program. More discussion of the program follows the listing.
// Import the basic graphics classes.
import java.awt.*;
import javax.swing.*;
/**
* Simple program that loads, rotates and displays an image.
* Uses the file Duke_Blocks.gif, which should be in
* the same directory.
*
* @author MAG
* @version 20Feb2009
*/

public class RotateImage extends JPanel{

// Declare an Image object for us to use.
Image image;

// Create a constructor method
public RotateImage(){
super();
// Load an image to play with.
image = Toolkit.getDefaultToolkit().getImage("Duke_Blocks.gif");
}

public void paintComponent(Graphics g){
Graphics2D g2d=(Graphics2D)g; // Create a Java2D version of g.
g2d.translate(170, 0); // Translate the center of our coordinates.
g2d.rotate(1); // Rotate the image by 1 radian.
g2d.drawImage(image, 0, 0, 200, 200, this);
}

public static void main(String arg[]){
JFrame frame = new JFrame("RotateImage");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600,400);

RotateImage panel = new RotateImage();
frame.setContentPane(panel);
frame.setVisible(true);
}
}

Most of this program is the same as our previous one. There are a couple of significant changes, however.

One is the following line:
Graphics2D g2d=(Graphics2D)g;
In this line we're doing what's known as a "cast". We're declaring a new Graphics2D object, naming it g2d, then setting its value to our present Graphics object, g. But since g is a Graphics object, and not a Graphics2D object, we're telling it to treat g as a Graphics2D object for the purposes of this assignment. We can get away with doing this because Graphics2D is a subclass of Graphics, which makes the two classes compatible enough to allow the cast to be successful.

By doing this, we "magically" make all the Graphics2D functions available for drawing to our window.

What we want to do is rotate our image. Since we don't want to have the image go outside our graphics area when we rotate it, I've moved our "point of origin" of our graphics area using
g2d.translate(170, 0);
This moves the center point around which the drawing area is rotated from the upper left corner of the window's display area to a point 170 pixels to the right of that.

Then we use the rotate() method of our Graphics2D object, which will cause everything drawn into it to be rotated:
g2d.rotate(1);
The amount we're rotating is 1 radian, or about 57 degrees, noted by the 1 inside the parentheses.

Then we use the drawImage method of our Graphics2D object to actually draw the image into our display area.

Experiment with different values for the rotate() method to see rotation at different angles. If you lose part of the image off the edge of the window, try to use different offsets in the drawImage() method to change the location within the window at which the image gets drawn.

This is a fairly simple method for rotating an image in Java. It has some value for creating static images that are rotated, but for something like sprites in a game it's not very useful. The best method for that would be to create rotated images in a graphics program, not in your Java program. It's possible to rotate your images in Java, but it gets complicated because you have to worry about a lot of things that your graphics program does for you, like the area your new image will fill relative to the original, the background of the image, and so on.

Once you have image files of your sprite in all its possible rotated angles, load all these images to different Image object in a Java program (or better yet, an Image array or Collection), and change between them to show the image rotating.
StumbleUpon

Thursday, July 17, 2008

Stars in import Statements

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

These are some representative import statments. Each one has an asterisk (or "star") at the end of it. What does that mean?

The asterisk is a special pattern-matching character. It matches any combination of characters (letters, numbers, or special characters.) In other words, it will match any name of any class in the package. Let's say we want to import Frame, Panel, Component, Color, Dialog, Dimension, Graphics and Image from the java.awt package for a program we're writing. We could have the following import statements:
import java.awt.Frame;
import java.awt.Panel;
import java.awt.Component;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;

Since star can take the place of any name, we can replace all of those import statements with one:
import java.awt.*;

This imports every class in java.awt. It also imports all the interfaces, exceptions, and errors defined in java.awt. It makes absolutely everything in the java.awt package available to our program.

OK, then why do we need to do this?
import java.awt.*;
import java.awt.event.*;

If the * makes us get everything in java.awt, why do we need to then go an import java.awt.event.*?

The reason is that java.awt.event is a different package than java.awt. The stuff in java.awt.event isn't actually in java.awt. With package names, the dot notation is just a way of letting us know that the stuff in java.awt.event is related to the stuff in java.awt, and that we'll probably want to use the stuff in these packages together. But java.awt.event isn't in java.awt, the way that System.out is in the class System.

Just remember, every package with its own name is a totally different package. You can tell a class name from a package name by whether it is capitalized:
import java.awt.Color;

Color is a class in the java.awt package. This is one of the reasons we follow the convention of using a capital letter at the start of a class's name. Whereas this:
import java.awt.color.*;

is an import of the classes in the java.awt.color package. These classes are not in java.awt, so you can't import them using "import java.awt.*;"

The asterisk is a "regular expression" character. It and a number of other characters are a way of building up what are called regular expressions, which are a way of matching things without using the precise name. The asterisk is a "wildcard," it can stand for any character, or any number of any characters.
StumbleUpon