You can program in Java (or are learning to.) That's great! But what else can you do with those skills? Are you trapped with Java?
Not at all. One of the reasons I chose Java as a language for use in the classroom is that Java programming skills translate so well into skills for other languages. Here are some other languages, and a brief look at what your Java programming skills will give you in the way of a head start, and what differences to look out for.
C# (C Sharp)
C# and Java are practically the same. C#'s roots are in Java, as is the concept of its libraries relative to Java's API. The libraries differ, but if you're used to Java's API you'll have no trouble getting right into C#'s libraries to find the classes you're looking for.
The major development tools are very similar, or, in many cases, you can use the same IDEs for C# as for Java. You can also do cross-platform development in C# just as you can with Java thanks to tools like Mono (which I highly recommend as a way of becoming familiar with C#) and the forthcoming cross-platform Visual Studio tools from Microsoft.
C
Java is an object-oriented descendent from the C language. C does not have object-orientation built in, but you should have no trouble understanding much of the code. Imagine writing Java without creating your own classes, or only creating limited classes. This isn't strictly accurate, since it is possible to write object-oriented code in C, it just requires the programmer to do much of the work that Java does in their code. Providing for isolation of data, inheritance, etc. has to be performed through code written explicitly to perform these functions.
Modern versions of C, such as ANSI C/ISO C (C99) provide a version of C which makes it easier to write good code if you're coming from an object-oriented background.
Another major hurdle will be dealing with memory management directly (C has no garbage collection), and learning how to use the various functions of C which are often not as predictable as the Java methods you are familiar with.
The basics of C will already be familiar to you, but you should conduct some formal study of C and use its standard libraries extensively before seeking to start formal projects with it.
C++
C++ is another object-oriented outgrowth of C, like Java, yet it uses a very different approach. You will find that your Java experience can be very misleading with respect to the handling of data and the operation of methods in C++. Also, C++'s libraries tend to be much more platform-specific than those of Java. In Java you have platform-specific libraries, yet it is possible to write good code that does not rely on it, or that relies on it little enough to allow 90% or more of your code to be written in a non-platform-specific fashion.
With C++, however, you'll find that while there are standard cross-platform libraries, most code will be best written to the platform to which it is being compiled.
Python
Python will be very easy to learn once you know Java. Its syntax is quite different, and its approach to what is implicit and what must be explicitly defined is very different to that of Java. Conceptually, however, you will be right at home and will be able to learn the specifics of the language very easily.
Like Java, Python has extensive libraries. Some are part of Python's core distribution, but others are not. You will find that even in the core libraries there is much less cross-platform support than Python seems to promise. Also, you will need platform-specific libraries for any graphics or audio code. Even in cross-platform libraries, you will find that there are significant differences between platforms. If you are writing code that does not rely on the platform for presentation, however, (for example code that uses a browser), Python works very well in a cross-platform environment.
Javascript
Javascript is also very similar to Java in many ways, but not as much as the name of the language might lead you to believe. Java has recently acquired many of the constructs that have been favorites of Javascript programmers for years.
You will find that handling data under Javascript is very different to the means used in Java. You will also find the nomenclature very, very different, despite the similarities in the languages. This will probably be your biggest early hurdle in transitioning from one language to the other.
The best approach is to set yourself to learn the ways that things are best done in Javascript, before trying to write Java code in Javascript syntax. Once you can write solid small programs, enough will become apparent to you that you can begin to take advantage of your programming knowledge from Java to apply it to your Javascript programs. Some programming languages it is your knowledge of Java syntax and structure that will make those languages easy for you. Javascript isn't one of those languages. The payoff comes after you have learned Javascript syntax and structure, the process of designing well-build object oriented software will pay off.
With Javascript, the web browser is almost certain to be your "platform." You will need to learn the Domain Object Model to effectively apply Javascript. If you have already been using the DOM with your Java code (over half of Java code is written for the web), then you are already there. Otherwise, it's something else new you'll have to learn.
Objective-C
The transition from Java to Objective-C is far simpler than to C++. The object-oriented techniques used in Objective-C will make immediate sense to a Java programmer, as will the program structure. Objective-C requires you to do your own memory management, unlike Java, but it provides facilities to do so more simply and effectively than standard C.
The libraries will differ completely from those of Java, and your platform will almost certainly be iOS or Macintosh, so those are the platforms whose libraries you'll learn. Objective-C differs from Java more than C#, but not so much as to make it extremely difficult to transition to. After C#, Objective-C is probably the easiest non-scripting language for you to learn.
Swift
Swift is based on Objective-C, and will be even easier for a Java programmer to learn and use. Most of the changes not only make it easier to produce programs in general, but make it conceptually simpler for a Java programmer to make the transition. You'll be reading the code in the first day, and will be able to produce effective code with only a few hours of work. As with Objective-C, there are new libraries for you to learn tied to Swift's platforms (iOS and Mac), but you will find these even easier to navigate than the Java libraries that suffer from Java's early history of development being encased within them.
PHP
PHP does not have the sort of object-oriented programming facilities that you will be used to from Java, but its syntax will be easy for you to pick up. You will likely feel limited by PHP compared to Java, but PHP has a more limited purpose than Java--it is focused on web programming. While Java is heavily used for server-side web programming, it is much more of a general purpose language than PHP.
You will need to learn the specifics of PHP's syntax and data structures, but after mastering Java, you will not find this difficult.
Summary
These cover the most popular programming languages in use at this time. There are other languages, like Scala, that are specifically designed to be like Java yet address shortcomings perceived in Java, either for some specific use, or to change things that are historically embedded in Java's design. These are very easy for a Java programmer to transition to.
At present, Oracle's support of Java is limiting its market relative to the general use for Java that Sun used to promote. While Java is still widely used, and will continue to be for the foreseeable future, it always behooves a programmer to be competent in multiple languages and to have more than one set of conceptual tools for problem solving at hand. So it is good to know other languages, even if they are scripting languages like Python and Ruby.
Currently, Microsoft is in the process of making a strong play to the cross-platform development market which Java has served. With C# as part of this, and C# plus Mono (a cross-platform version of .Net) already available, it is very easy for a Java programmer to add this to their programming portfolio to gain a greater range of opportunities for work, and a wider range of tools for solving programming problems.
I highly recommend, at least, spending some time with C# under Mono or .Net if you are currently a Java programmer. I think you'll find that you feel right at home.
An advantage of learning .Net is that it will open up Windows-specific programming in C++ to you as well. The C++ language will be new, but you'll already know the libraries that you'll be using. If Microsoft delivers on their recent promises of making their tools fully cross-platform for Mac and Linux, then you'll be able to apply those skills to those platforms as well.
Mobile
Java is the language you'll use on Android, currently the dominant mobile platform in terms of users. Objective-C is the language for iOS, and it's not a huge jump for a Java programmer to make. Swift is a simplified version of Objective-C, and it is even easier for the Java programmer to learn. If you are planning to develop for iOS, it is worth making the effort to transition to a language built for it, and Swift should be your first stop.
Showing posts with label graphics. Show all posts
Showing posts with label graphics. Show all posts
Monday, November 17, 2014
Portability of Java Programming Skills
Labels:
Android,
API,
application,
C,
C#,
C++,
cross-platform,
environment,
graphics,
IDE,
Java,
Javascript,
PHP,
Swift,
web,
why java

Thursday, September 2, 2010
Interactive Keyboard Input In Java: KeyListeners
In a console application, you can get keyboard input using the Scanner class, as described in Keyboard Input for Console Apps. In an graphical app, though, you can use one of the classes built to accept text input (e.g. TextArea or JTextField) or add code to your application to respond directly to the keyboard.

There are two basic ways of doing this. One is to set up Key Bindings, which maps keystrokes to actions in your application similar to accelerator keys or menu keyboard equivalents. The other is to use a Key Listener, similar to the Mouse Listener, which I detailed in Simple Mouse Interaction.
In this example we're going to use Key Listeners. There is less overhead to setting up a KeyListener when you just need to use a few keys. Key Bindings require more overhead to set up, but when you want to bind actions to a lot of different keystrokes, and manage the actions bound to particular keystrokes at a higher level, Key Bindings are better to use than a simple KeyListener.
As its name implies, a KeyListener is an Event Listener. If you're not sure what that is, read my article on Listeners or follow the prior link to Oracle/Sun's description.
Here's a program that demonstrates simple keyboard interaction. It's based on the MousePanel program I presented in Simple Mouse Interaction. It acts as a sort of "Etch-a-Sketch". You can download the KeyPanel program source from my Java code site.
Using this technique with the Simple Video Game Kernel would be similar. The VGKernel would extend KeyListener, register itself, and implement the KeyListener methods. But in those methods, rather than performing the operations that result from the keypress, as in this program, you would want to simply set a flag to show that the key has been pressed. Then, in your core game logic you would test to see whether the key has been pressed, and perform the appropriate actions.
That way the actions are performed at the appropriate time in your game, and not just whenever the key happens to get pressed. Reacting to a key when it is pressed is appropriate for a turn-based game, but not for a real-time game. In a real-time game the action happens according to the timing of the TimerTask that drives the game, which is why we just note that a key has been pressed, and wait until the TimerTask occurs to actually conduct the action related to that key. This would be similar to what we do with the space key here, which sets a flag to tell paintComponent() to erase the screen.
Give this program a try, see if you can extend it to allow the user to select colors to draw with or change the size of the drawing pen.
Playing with Today's Program
There are two basic ways of doing this. One is to set up Key Bindings, which maps keystrokes to actions in your application similar to accelerator keys or menu keyboard equivalents. The other is to use a Key Listener, similar to the Mouse Listener, which I detailed in Simple Mouse Interaction.
In this example we're going to use Key Listeners. There is less overhead to setting up a KeyListener when you just need to use a few keys. Key Bindings require more overhead to set up, but when you want to bind actions to a lot of different keystrokes, and manage the actions bound to particular keystrokes at a higher level, Key Bindings are better to use than a simple KeyListener.
As its name implies, a KeyListener is an Event Listener. If you're not sure what that is, read my article on Listeners or follow the prior link to Oracle/Sun's description.
Here's a program that demonstrates simple keyboard interaction. It's based on the MousePanel program I presented in Simple Mouse Interaction. It acts as a sort of "Etch-a-Sketch". You can download the KeyPanel program source from my Java code site.
// Import the basic necessary classes.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class KeyPanel extends JPanel implements KeyListener{
public KeyPanel(){
super();
pointX=0;
pointY=0;
oldX=0;
oldY=0;
addKeyListener(this);
}
int pointX, pointY, oldX, oldY;
boolean erase;
public void paintComponent(Graphics g){
// Erase the board if it's been requested.
if (erase) {
g.clearRect(0, 0 , getBounds().width, getBounds().height);
erase = false; // We're done, turn off this flag now.
}
// Draw gray where the pointer was..
g.setColor(Color.GRAY);
g.fillRect(oldX-2, oldY-2, 4, 4);
// Draw "Cursor" at current location in black.
g.setColor(Color.BLACK);
g.fillRect(pointX-2,pointY-2, 4, 4);
}
public void keyPressed(KeyEvent key){
// Copy the last clicked location into the 'old' variables.
oldX=pointX;
oldY=pointY;
// Move the current point depending on which key was pressed.
if (key.getKeyCode() == key.VK_DOWN){
pointY=pointY+5;
if (pointY > getBounds().height){
pointY=getBounds().height;
}
}
if (key.getKeyCode() == key.VK_UP){
pointY=pointY-5;
if (pointY < 0){pointY=0;}
}
if (key.getKeyCode() == key.VK_LEFT){
pointX=pointX-5;
if (pointX < 0){pointX=0;}
}
if (key.getKeyCode() == key.VK_RIGHT){
pointX=pointX+5;
if (pointX > getBounds().width){
pointX=getBounds().width;
}
}
// Set a flag to erase the screen if Space is pressed.
if (key.getKeyCode() == key.VK_SPACE){
erase = true;
}
// Tell the panel that we need to redraw things.
repaint();
}
/* The following methods have to be here to comply
with the MouseListener interface, but we don't
use them, so their code blocks are empty. */
public void keyTyped(KeyEvent key){ }
public void keyReleased(KeyEvent key){ }
public static void main(String arg[]){
JFrame frame = new JFrame("Use Arrows to Draw, Space to Erase.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(640,480);
KeyPanel panel = new KeyPanel();
frame.setContentPane(panel);
frame.setVisible(true);
// We *must* do this to see KeyEvents.
panel.setFocusable(true);
// Initialize the drawing pointer.
panel.oldX=panel.getBounds().width/2;
panel.oldY=panel.getBounds().height/2;
panel.pointX=panel.oldX;
panel.pointY=panel.oldY;
}
}
Using this technique with the Simple Video Game Kernel would be similar. The VGKernel would extend KeyListener, register itself, and implement the KeyListener methods. But in those methods, rather than performing the operations that result from the keypress, as in this program, you would want to simply set a flag to show that the key has been pressed. Then, in your core game logic you would test to see whether the key has been pressed, and perform the appropriate actions.
That way the actions are performed at the appropriate time in your game, and not just whenever the key happens to get pressed. Reacting to a key when it is pressed is appropriate for a turn-based game, but not for a real-time game. In a real-time game the action happens according to the timing of the TimerTask that drives the game, which is why we just note that a key has been pressed, and wait until the TimerTask occurs to actually conduct the action related to that key. This would be similar to what we do with the space key here, which sets a flag to tell paintComponent() to erase the screen.
Give this program a try, see if you can extend it to allow the user to select colors to draw with or change the size of the drawing pen.
Labels:
application,
graphics,
listeners,
video game

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.
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.

Sunday, August 22, 2010
More Collision Detection: Bouncing the Right Way
A common result of a collision between two objects in a video game is a bounce. To do this right, we have to know which direction to make things bounce. Here's one way to do that easily in Java. I've got a ball that's going to bounce in one of eight directions depending on how it hits a brick.

I've marked the changes to the ball's velocity that will occur as a result of each possible type of collision. The three arrows on the left side all show that the xVel (x velocity) is a negative value, the three arrows on the bottom all show that yVel (y velocity) should become a positive value.
In the cases of the corners, both the x and y velocities are set. The bounces off the middles of the sides all cause one velocity to be set, but the other is left alone. For example, a bounce off the right side of the brick sets the xVel to a positive value, but the yVel is unchanged. So if yVel was a positive value before (meaning the ball is travelling down on screen) then it will keep travelling down. If it was negative--moving up--then it will keep moving up. Only the x direction of movement will change. It will start moving from left to right instead of right to left.
It's really easy to detect a collision, but now we need to know the relationship between the two colliding objects so that we can make the ball bounce in the correct direction. As we learned in Stopping Jonathan Livingston Seagull, the effect of how much we move an object before we check a collision can cause problems if we don't understand the limits of how we detect them.
In this program, our ball's movement is presently set at one quarter of its width. We could go as high as one half its width and still have our collision detection routines work properly here. Fortunately, we want to keep the distance the ball moves each turn short to make the movement look smoother.
When we hit the brick, we want to see where it hits the ball. This will tell the ball which way to bounce, just like a real ball. In the drawing above, we have a red brick on a cyan (blue-green) playfield. The ball is dark blue. Where the ball is intersecting, or overlapping, the brick is shown in yellow. Now we just need to know which side of the ball is getting "pushed in" this way. Then we bounce the opposite way.
Here's the program, the key code we're talking about is highlighted:
The way we figure out which way to bounce is to find the center of the ball and the center of the intersection rectangle (the yellow box in the picture, where the ball and the brick overlap.) Then if the center of the intersection (shown as an orange dot on the pic) is to the right of the center of the ball (a white dot) we bounce left. If it's to the left, we bounce right, if it's above we bounce down, below we bounce up.
This way we don't have to worry about the size or shape of the brick itself. All we care about is the bit that strikes the ball. Then the ball bounces the correct way.
If we had wanted to get really fancy, we could have made the ball bounce at different angles depending on the angle between the center of the ball and the center of the intersection rectangle. If you're familiar with trigonometry, take a look at the Math class in Java and see if you can implement this.
I've marked the changes to the ball's velocity that will occur as a result of each possible type of collision. The three arrows on the left side all show that the xVel (x velocity) is a negative value, the three arrows on the bottom all show that yVel (y velocity) should become a positive value.
In the cases of the corners, both the x and y velocities are set. The bounces off the middles of the sides all cause one velocity to be set, but the other is left alone. For example, a bounce off the right side of the brick sets the xVel to a positive value, but the yVel is unchanged. So if yVel was a positive value before (meaning the ball is travelling down on screen) then it will keep travelling down. If it was negative--moving up--then it will keep moving up. Only the x direction of movement will change. It will start moving from left to right instead of right to left.
It's really easy to detect a collision, but now we need to know the relationship between the two colliding objects so that we can make the ball bounce in the correct direction. As we learned in Stopping Jonathan Livingston Seagull, the effect of how much we move an object before we check a collision can cause problems if we don't understand the limits of how we detect them.
In this program, our ball's movement is presently set at one quarter of its width. We could go as high as one half its width and still have our collision detection routines work properly here. Fortunately, we want to keep the distance the ball moves each turn short to make the movement look smoother.
When we hit the brick, we want to see where it hits the ball. This will tell the ball which way to bounce, just like a real ball. In the drawing above, we have a red brick on a cyan (blue-green) playfield. The ball is dark blue. Where the ball is intersecting, or overlapping, the brick is shown in yellow. Now we just need to know which side of the ball is getting "pushed in" this way. Then we bounce the opposite way.
Here's the program, the key code we're talking about is highlighted:
/* A simple video game style kernel, revision 4.
by Mark Graybill, August 2010
Has a ball bouncing off a brick.
Because the ball moves at a fixed speed,
slow enough we won't miss a collision,
we can use simple colliision detection.
Uses the Brick class from the article
"Multiple Constructor Methods"
*/
import java.util.*;
import java.awt.*;
import javax.swing.*;
import java.lang.Math;
public class VidBrick extends JPanel{
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, a subclass of Rectangle.
private Brick brick; // A brick for the ball to interact with.
/* This sets up the screen area, and creates instances of
the JFrame, VGBall, VGTimerTask, etc that we'll need. */
public VidBrick(){
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("VidBrick");
vgTask = new VGTimerTask();
brick = new Brick();
}
class VGTimerTask extends TimerTask{
public void run(){
ball.move();
frame.repaint();
}
}
class VGBall extends Rectangle{
int xVel, yVel; // The ball's velocity.
Color ballColor; // The color of the ball.
/* Create a VGBall with default location of upper left
corner, size of 20x20 pixels, moving at one quarter
its height and width per turn--plus it's blue. */
public VGBall(){
super(0, 0, 20, 20);
xVel = width/4;
yVel = height/4;
ballColor=new Color(0, 0, 128);
}
/* Move the Ball. */
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; }
// Detect Brick and bounce if necessary.
if (intersects(brick)) {
// Get the intersection rectangle to find out which way to bounce.
Rectangle iRect = intersection(brick);
// If we hit on the left side, go left (negative x velocity).
if ((x+(width/2))<(iRect.x+(iRect.width/2))){xVel=(0-Math.abs(xVel));}
// If we hit on the right side, go right (positive x velocity).
if ((x+(width/2))>(iRect.x+(iRect.width/2))){xVel=Math.abs(xVel);}
// If we hit on the top, go up.
if ((y+(height/2))<(iRect.y+(iRect.height/2))){yVel=(0-Math.abs(yVel));}
// If we hit on the bottom, go down.
if ((y+(height/2))>(iRect.y+(iRect.height/2))){yVel=Math.abs(yVel);}
} // if intersects
}
/* Draw the ball into the provided graphics context. Preserves
the context's drawing color setting. */
public void draw(Graphics g){
// the ball draws itself in the graphics context given.
Color gcColor = g.getColor(); // Preserve the present color.
g.setColor(ballColor); // Use the ball's color for the ball.
g.fillRect(x, y, width, height); // Draw the ball.
g.setColor(gcColor); // Restore prior color.
} // end draw()
} // end of class VGBall
public void paintComponent(Graphics g){
// Get the drawing area bounds for game logic.
bounds = g.getClipBounds();
// Clear the drawing area.
g.clearRect(screen.x, screen.y, screen.width, screen.height);
// Draw the brick.
g.setColor(brick.getColor());
g.fillRect(brick.x, brick.y, brick.width, brick.height);
// Draw the ball.
ball.draw(g);
}
/* Main program loop. */
public static void main(String arg[]){
java.util.Timer vgTimer = new java.util.Timer(); // Create a Timer object
VidBrick panel = new VidBrick();
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 the brick.
panel.brick.x = panel.screen.width/3;
panel.brick.y = panel.screen.height/3;
panel.brick.width = panel.screen.width/3;
panel.brick.height = panel.screen.height/3;
// Set up a timer to do the vgTask regularly.
vgTimer.schedule(panel.vgTask, 0, 33);
}
}
The way we figure out which way to bounce is to find the center of the ball and the center of the intersection rectangle (the yellow box in the picture, where the ball and the brick overlap.) Then if the center of the intersection (shown as an orange dot on the pic) is to the right of the center of the ball (a white dot) we bounce left. If it's to the left, we bounce right, if it's above we bounce down, below we bounce up.
This way we don't have to worry about the size or shape of the brick itself. All we care about is the bit that strikes the ball. Then the ball bounces the correct way.
If we had wanted to get really fancy, we could have made the ball bounce at different angles depending on the angle between the center of the ball and the center of the intersection rectangle. If you're familiar with trigonometry, take a look at the Math class in Java and see if you can implement this.
Labels:
collision detection,
graphics,
Math,
video game

Friday, August 20, 2010
Web Browsing on the Atari 2600???
A recent discussion on an Astronomy forum took a turn for the earthly with the announcement of a new web site at StellarVue Telescopes. People were checking it out, reporting on minor fixes they felt were necessary and trying it with different systems and OSes. Then came the first report of a total crash and burn. From a Commodore 64 user. Next we had reports of failures on Heathkit and Vic-20 systems, too.
"Aha," I thought," a perfect opportunity to try out my Web Surfer cartridge on my Atari 2600!"
Here are the results:

My Atari 2600 with the Web Surfer Cartridge,
Check out my Atari web page for more pictures and info on this amazing VCS cart!
"Aha," I thought," a perfect opportunity to try out my Web Surfer cartridge on my Atari 2600!"
Here are the results:

My Atari 2600 with the Web Surfer Cartridge,
Displaying the StellarVue Web Site.
Check out my Atari web page for more pictures and info on this amazing VCS cart!
Note to those following my Java Programming Stuff: I was supposed to post this over at my other blog, An Infinite Number of Cats on Keyboards, but I punched the wrong button on my Blogger Dashboard, and it ended up here instead. Sorry about that. Now back to our regularly scheduled Java program...
Labels:
graphics,
humor,
video game,
web

Wednesday, August 18, 2010
Stopping Jonathan Livingston Seagull with Java
In Simple Collision Detection we used the intersects() method of two Rectangle subclasses to see if one object struck another on our playfield. It works, in the example given. But in the example given the velocity of the ball is limited.

In the VGBKernel.java example, we have a fairly slow-moving ball detecting collisions with a really large object that's hard to miss.
If we have a brick that is small, and a ball that is fast, though, the ball could pass right over the brick without even realizing it should have collided with it. In other words, if we had a brick wall stretching across the screen, the ball might fly "through" it when we want it to stop or bounce. Let's say we're falling and want to detect a brick that acts as a floor. The floor goes across the screen between heights 100 and 105. The ball starts at location 75 and has a velocity of 50. Its new location would be 125. We move it there, and check for a collision as we did in VGBKernel. No collision. The ball just flew "through" the brick wall like Jonathan Livingston Seagull!
Let's make an example program called BallGrav.java to illustrate the problem. BallGrav.java is a slightly modified version of VGBKernel.java. It uses the same Brick class as we've used before, with no modifications.

But let's make the ball accelerate a bit faster. Make the following change in Ball's move() method:
Suddenly, the ball doesn't detect the floor any more, and it goes to the bottom of the screen, right through the floor:

Stopping Jonathan Livingston Gameball from Going Through the Wall
What do we do to keep this from happening? Well, one way is to never let the ball move faster than it can detect collisions. Then we'd never let it move more than its own size in any direction. If it's important that it know what side it hits something on (like when we're going to bounce off it), then we may not want to let it go more than half its size in any direction in any one "move." To do this to BallGrav,java, we'd change the code as follows:
Now the ball will never go so fast it never sees the floor.
But what if we want the ball to move faster?
In this case, there are a number of possible solutions. Many of them are fairly complicated, with lots of math or with lots of iteration checking for collisions at each step along the way. Complexity is something we don't want, for a lot of reasons. Here is one possible solution, that uses collision prediction to see if our ball might hit something along the way:
Here, I have a velocity limit twice as high as before. This allows the ball to move along a lot faster (before, I could see the ball slow down.) Now, since the ball can move fast enough to fly through things, we first look ahead to see if there's anything in the way. We do this by seeing if there's something halfway there. If so, we cut our original speed in half before we move. Then the collision (if any) happens "naturally."
This is good enough, if the fastest we can move is twice the ball's height. If we allowed three times its height, we might check at points 1/3 and 2/3 of the way along its path.
If we don't want limits like this, we pay the price by having a more complex method to check for collisions. Here, I've limited things to movement in only one direction, up and down. If we're going side to side as well, I'd have to check for waypoints along a diagonal path. To get really precise, I'd have to do something like project lines along the corners of the ball from its current position to its intended new position and see if they intersect anything. When you get into more complex shapes than the rectangles we're using now, you get a different set of choices.
Fortunately, for video games, simple choices are almost always plenty good enough. Checking for collisions at the minimum number of points along the path is almost always good enough. This can be done by dividing the distance to be moved by the largest safe move distance, and checking that many times for collisions along the path.
Avoiding the Problem Entirely
You can also just use a different sort of movement that never has any of the objects moving more than some small number of pixels at a time--small enough that you'll never fail to detect a collision. I'll give an example in a future article, but for now I'll just describe it.
What you do is set a speed at which you move things only, say, one pixel per "move". But you only move them every so often, depending on what their speed is. The fastest objects get moved on every redraw of the screen. Slower objects only get moved on every other update, or every fifth, or something of that sort. That way an object is never moved across the screen by so many pixels at once that it misses seeing a collision with another object.
Collision Detection: Never "Easy"
Collision detection is one of the programmer's bugaboos. It's one of the places where errors are most prone to occur in code, and it can have terrible effects on a game if it doesn't work properly. The programmer's choices are to accept certain limitations or to make more complex code, or to use a technique of object movement that can either be limiting or eat up a lot of processor time.
When my students program their video game projects in class, one of our biggest problems in implementing those games is dealing with collision detection. Even though we're working in Greenfoot, which does a lot of the work for us. We still need to be aware of the limitations built into the system, and work within them.
Now it's your turn. Try reducing the brick in BallGrav.java to a small platform. Now give the ball a constant x velocity. See if you can get the ball to land on that platform reliably, with successful collision detection.
If we have a brick that is small, and a ball that is fast, though, the ball could pass right over the brick without even realizing it should have collided with it. In other words, if we had a brick wall stretching across the screen, the ball might fly "through" it when we want it to stop or bounce. Let's say we're falling and want to detect a brick that acts as a floor. The floor goes across the screen between heights 100 and 105. The ball starts at location 75 and has a velocity of 50. Its new location would be 125. We move it there, and check for a collision as we did in VGBKernel. No collision. The ball just flew "through" the brick wall like Jonathan Livingston Seagull!
Let's make an example program called BallGrav.java to illustrate the problem. BallGrav.java is a slightly modified version of VGBKernel.java. It uses the same Brick class as we've used before, with no modifications.
/* Based on the video game style kernel, revision 3.This example functions properly. When the ball falls, it strikes the brick floor and stops.
by Mark Graybill, August 2010
Demonstrates collision detection problems, and solutions.
*/
// 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 BallGrav extends JPanel{
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, a subclass of Rectangle.
private Brick brick; // A brick for the ball to interact with.
// Create a constructor method:
public BallGrav(){
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("BallGrav");
vgTask = new VGTimerTask();
brick = new Brick();
}
// Create an inner TimerTask class that has access to the
// members of the BallGrav.
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 extends Rectangle{
int xVel, yVel; // The ball's velocity.
Color ballColor; // The color of the ball.
public VGBall(){
super(300, 0, 20, 20);
xVel = 0; // Start with 0 velocity at center top of screen.
yVel = 0;
ballColor=new Color(0, 0, 128);
}
// Instance methods for VGBall
public void move(){
// Accelerate due to "gravity".
yVel+=3;
// Move the ball according to the game rules.
x+=xVel; // Move horizontally.
y+=yVel; // Move vertically, accelerating as we go.
// Detect edges and stop movement if we hit them.
if (x > (bounds.width - width)){
xVel = 0; // stop movement.
x = bounds.width - width; // Set location to screen edge.
}
if (y > (bounds.height - height)){
yVel = 0; // stop movement.
y = bounds.height - height;
}
if (x <= 0) { xVel = 0; x = 0; }
if (y <= 0) { yVel = 0; y = 0; }
// Check for intersection with Brick,
// change color when touching.
if (intersects(brick)) {
//Stop on top of the brick if we hit it.
yVel = 0;
y = brick.y - height;
}
}
public void draw(Graphics g){
// the ball draws itself in the graphics context given.
Color gcColor = g.getColor(); // Preserve the present color.
g.setColor(ballColor); // Use the ball's color for the ball.
g.fillRect(x, y, width, height); // Draw the ball.
g.setColor(gcColor); // Restore prior color.
} // end draw()
} // 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.
g.clearRect(screen.x, screen.y, screen.width, screen.height);
// Draw the brick.
g.setColor(brick.getColor());
g.fillRect(brick.x, brick.y, brick.width, brick.height);
// Draw the ball.
ball.draw(g);
}
public static void main(String arg[]){
java.util.Timer vgTimer = new java.util.Timer(); // Create a Timer object
BallGrav panel = new BallGrav();
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 the brick.
panel.brick.x = 0;
panel.brick.y = 4 * (panel.screen.height/5);
panel.brick.width = panel.screen.width;
panel.brick.height = 5;
panel.brick.brickColor = new Color(200,50,50);
// Set up a timer to do the vgTask regularly.
vgTimer.schedule(panel.vgTask, 250, 200);
}
}
But let's make the ball accelerate a bit faster. Make the following change in Ball's move() method:
// Accelerate due to "gravity".
yVel+=5;
Suddenly, the ball doesn't detect the floor any more, and it goes to the bottom of the screen, right through the floor:
Stopping Jonathan Livingston Gameball from Going Through the Wall
What do we do to keep this from happening? Well, one way is to never let the ball move faster than it can detect collisions. Then we'd never let it move more than its own size in any direction. If it's important that it know what side it hits something on (like when we're going to bounce off it), then we may not want to let it go more than half its size in any direction in any one "move." To do this to BallGrav,java, we'd change the code as follows:
// Accelerate due to "gravity".
yVel+=5;
// Limit our velocity to preserve collisions.
if (yVel>height) { yVel = height; }
Now the ball will never go so fast it never sees the floor.
But what if we want the ball to move faster?
In this case, there are a number of possible solutions. Many of them are fairly complicated, with lots of math or with lots of iteration checking for collisions at each step along the way. Complexity is something we don't want, for a lot of reasons. Here is one possible solution, that uses collision prediction to see if our ball might hit something along the way:
// Accelerate due to "gravity".
yVel+=5;
// Limit our velocity.
if (yVel>(height*2)) { yVel = height * 2; }
// Move the ball according to the game rules.
// Check for a collision if we're moving fast.
if (yVel>height) {
Rectangle halfway = new Rectangle(x,y+(yVel/2), width, height);
if (halfway.intersects(brick)) { yVel = yVel/2; }
}
x+=xVel; // Move horizontally.
y+=yVel; // Move vertically, accelerating as we go.
Here, I have a velocity limit twice as high as before. This allows the ball to move along a lot faster (before, I could see the ball slow down.) Now, since the ball can move fast enough to fly through things, we first look ahead to see if there's anything in the way. We do this by seeing if there's something halfway there. If so, we cut our original speed in half before we move. Then the collision (if any) happens "naturally."
This is good enough, if the fastest we can move is twice the ball's height. If we allowed three times its height, we might check at points 1/3 and 2/3 of the way along its path.
If we don't want limits like this, we pay the price by having a more complex method to check for collisions. Here, I've limited things to movement in only one direction, up and down. If we're going side to side as well, I'd have to check for waypoints along a diagonal path. To get really precise, I'd have to do something like project lines along the corners of the ball from its current position to its intended new position and see if they intersect anything. When you get into more complex shapes than the rectangles we're using now, you get a different set of choices.
Fortunately, for video games, simple choices are almost always plenty good enough. Checking for collisions at the minimum number of points along the path is almost always good enough. This can be done by dividing the distance to be moved by the largest safe move distance, and checking that many times for collisions along the path.
Avoiding the Problem Entirely
You can also just use a different sort of movement that never has any of the objects moving more than some small number of pixels at a time--small enough that you'll never fail to detect a collision. I'll give an example in a future article, but for now I'll just describe it.
What you do is set a speed at which you move things only, say, one pixel per "move". But you only move them every so often, depending on what their speed is. The fastest objects get moved on every redraw of the screen. Slower objects only get moved on every other update, or every fifth, or something of that sort. That way an object is never moved across the screen by so many pixels at once that it misses seeing a collision with another object.
Collision Detection: Never "Easy"
Collision detection is one of the programmer's bugaboos. It's one of the places where errors are most prone to occur in code, and it can have terrible effects on a game if it doesn't work properly. The programmer's choices are to accept certain limitations or to make more complex code, or to use a technique of object movement that can either be limiting or eat up a lot of processor time.
When my students program their video game projects in class, one of our biggest problems in implementing those games is dealing with collision detection. Even though we're working in Greenfoot, which does a lot of the work for us. We still need to be aware of the limitations built into the system, and work within them.
Now it's your turn. Try reducing the brick in BallGrav.java to a small platform. Now give the ball a constant x velocity. See if you can get the ball to land on that platform reliably, with successful collision detection.
Labels:
collision detection,
graphics

Sunday, August 15, 2010
Simple Collision Detection in Java
Collision detection is a basic element of a video game. It is one of the primary means of determining when objects in a game should interact. In Asteroids, there are collisions between the player's shot and the asteroids themselves. There are collisions between the player's shot and the alien spacecraft (hopefully.) There are collisions between the asteroids and the player's ship (argh!) Each of these is critical to the game.

Since we don't have actual physics to determine when there's been a collision, as we have in real life, we need to create a set of rules for when a collision has occured then implement those rules in our code. One way to handle collision detection is to see if two potentially colliding objects intersect at all on the playfield. That is, whether one of them overlays the other.
Previously, we have worked with a simple video game kernel, then updated it to make the addition of game logic simpler. We had also created a Brick class that we can use to interact with the ball in our basic video game kernel.
Here is a slightly changed version of the simple video game kernel. It uses the Brick class, so Brick.class should be in the same directory as your VGBKernel.java and VGBKernel.class (it wouldn't be a bad idea to have Brick.java there, too, in case you want to play around with it at all to get different effects with this program through changes of your own.)
The main changes here are the addition of the brick to the VGBKernel (that's why I renamed VGKernel to VGBKernel, by the way--it's now a Video Game Brick Kernel), and I've changed ball into an extension of Rectangle to make collision detection a bit easier.
To do the actual collision detection, I'm using the method intersects() from the Rectangle class. It tests whether one Rectangle overlaps another in the coordinate space.
In this case, if the ball is on top of the brick (a rather large brick), then the ball turns green. I could have had any of a number of other effects. For example, when I was first testing this routine I didn't change the color of the ball, instead I had the ball send a message to the Java console that read "Ow!". So whenever the ball passed over the brick I'd get a long string of messages in the console like this:
I could just as well have the program play a sound, draw an image, update a score, or any of a number of different things when a collision occurs. Exactly what should happen is determined by the rules of the video game itself.
Going Further
Try changing the effect when the ball strikes the brick. The easiest place to start would be making the ball a different color than green. To get more sophisticated, try things like adding a sound, or counting the number of moves that the ball is in contact with the brick. Change the size and location of the brick. Perhaps try adding additional bricks, and have each create a different effect. Try changing the color of the brick when the ball strikes it.
One thing about the collision detection we are doing here. It only detects when we have actually started to overlap with the brick. In many cases, it's desirable to predict when a collision will occur as a result of a move before that move occurs. Try to develop a solution to this yourself. I'll be addressing this in a future article, so you can compare what you came up with against my method. Remember that in programming there's almost never just one way to accomplish something. The same effect can usually be produced any of a number of different ways effectively enough to use in a finished program.
Since we don't have actual physics to determine when there's been a collision, as we have in real life, we need to create a set of rules for when a collision has occured then implement those rules in our code. One way to handle collision detection is to see if two potentially colliding objects intersect at all on the playfield. That is, whether one of them overlays the other.
Previously, we have worked with a simple video game kernel, then updated it to make the addition of game logic simpler. We had also created a Brick class that we can use to interact with the ball in our basic video game kernel.
Here is a slightly changed version of the simple video game kernel. It uses the Brick class, so Brick.class should be in the same directory as your VGBKernel.java and VGBKernel.class (it wouldn't be a bad idea to have Brick.java there, too, in case you want to play around with it at all to get different effects with this program through changes of your own.)
/* A simple video game style kernel, revision 3.
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 VGBKernel extends JPanel{
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, a subclass of Rectangle.
private Brick brick; // A brick for the ball to interact with.
// Create a constructor method:
public VGBKernel(){
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("VGBKernel");
vgTask = new VGTimerTask();
brick = new Brick();
}
// Create an inner TimerTask class that has access to the
// members of the VGBKernel.
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 extends Rectangle{
int xVel, yVel; // The ball's velocity.
Color ballColor; // The color of the ball.
public VGBall(){
super(0, 0, 20, 20);
xVel = width/4;
yVel = height/4;
ballColor=new Color(0, 0, 128);
}
// 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; }
// Check for intersection with Brick,
// change color when touching.
if (intersects(brick)) { ballColor=Color.GREEN; }
else { ballColor=Color.BLUE; }
}
public void draw(Graphics g){
// the ball draws itself in the graphics context given.
Color gcColor = g.getColor(); // Preserve the present color.
g.setColor(ballColor); // Use the ball's color for the ball.
g.fillRect(x, y, width, height); // Draw the ball.
g.setColor(gcColor); // Restore prior color.
} // end draw()
} // 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.
g.clearRect(screen.x, screen.y, screen.width, screen.height);
// Draw the brick.
g.setColor(brick.getColor());
g.fillRect(brick.x, brick.y, brick.width, brick.height);
// Draw the ball.
ball.draw(g);
}
public static void main(String arg[]){
java.util.Timer vgTimer = new java.util.Timer(); // Create a Timer object
VGBKernel panel = new VGBKernel();
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 the brick.
panel.brick.x = panel.screen.width/4;
panel.brick.y = panel.screen.height/4;
panel.brick.width = panel.screen.width/2;
panel.brick.height = panel.screen.height/2;
// Set up a timer to do the vgTask regularly.
vgTimer.schedule(panel.vgTask, 0, 33);
}
}
The main changes here are the addition of the brick to the VGBKernel (that's why I renamed VGKernel to VGBKernel, by the way--it's now a Video Game Brick Kernel), and I've changed ball into an extension of Rectangle to make collision detection a bit easier.
To do the actual collision detection, I'm using the method intersects() from the Rectangle class. It tests whether one Rectangle overlaps another in the coordinate space.
In this case, if the ball is on top of the brick (a rather large brick), then the ball turns green. I could have had any of a number of other effects. For example, when I was first testing this routine I didn't change the color of the ball, instead I had the ball send a message to the Java console that read "Ow!". So whenever the ball passed over the brick I'd get a long string of messages in the console like this:
Ow!
Ow!
Ow!
Ow!
Ow!
Ow!
Ow!
Ow!
Ow!
I could just as well have the program play a sound, draw an image, update a score, or any of a number of different things when a collision occurs. Exactly what should happen is determined by the rules of the video game itself.
Going Further
Try changing the effect when the ball strikes the brick. The easiest place to start would be making the ball a different color than green. To get more sophisticated, try things like adding a sound, or counting the number of moves that the ball is in contact with the brick. Change the size and location of the brick. Perhaps try adding additional bricks, and have each create a different effect. Try changing the color of the brick when the ball strikes it.
One thing about the collision detection we are doing here. It only detects when we have actually started to overlap with the brick. In many cases, it's desirable to predict when a collision will occur as a result of a move before that move occurs. Try to develop a solution to this yourself. I'll be addressing this in a future article, so you can compare what you came up with against my method. Remember that in programming there's almost never just one way to accomplish something. The same effect can usually be produced any of a number of different ways effectively enough to use in a finished program.
Labels:
collision detection,
graphics,
inner class,
video game

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.
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.
Labels:
classes,
graphics,
inner class

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.

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:
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.
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.
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.
Labels:
classes,
graphics,
inner class,
JFrame,
JPanel,
video game

Wednesday, August 4, 2010
A Simple Java Video Game Kernel
Most video games run continuously, rather than waiting for user input before they do something. The heart of a video game of this sort is called the kernel. The kernel is running in the background, collecting user input and updating the display. It uses logic to determine if the game has been won or lost or otherwise control the state of the game.

To run this way, Threads are usually used to allow more than one thing to be going on at a time in a Java program. We've looked at a simple way of using threads before, the Timer class.
Here's a really, really simple video game kernel. It has all the basic elements of a video game.
This example can be expanded with methods to get control inputs, additional players on the playfield (like paddles), and logic to determine when someone scores.
The code here is far from perfect, but I've made some compromises to make things as simple as I could while still showing a full working example. Not that any code that runs and does what is supposed to is really bad, but there are other, better ways of doing this. But this works and is fairly easy to understand.
What the program does is create a JPanel that has an inner class (a class defined within itself) of VGTimerTask. The VGTimerTask is a kind of TimerTask, which can be scheduled to occur on a regular basis by a Timer. Since VGTimerTask is an inner class of VGPanel, it has access to all the members of VGPanel. This is critical. Without that, it wouldn't be able to access the ball and redraw the screen easily (it can still be done, but in a more complex way.)
Timer is a decent way of running a simple game, but more complex games should use some other timing mechanism. java.util.Timer is affected by a number of outside events, so to get smoother, more reliable timing you a timer like the one in the Java3D package would work better.
There are many ways of improving on this basic example. One way that is very simple is to smooth the animation. The movement of the ball is pretty jerky. This is caused by both the distance that the ball moves each "turn", and by the time between screen updates. We can smooth out the animation by addressing both of these.
First, let's change moveBall() to shift the ball a smaller distance each time:
Next, change the Timer schedule to draw the screen every 20 milliseconds instead of every 100 milliseconds:
Now you have a ball that moves a lot smoother.
I'll be expanding on this basic kernel and improving it in future articles, starting with Java Video game Programming: Game Logic
This simple kernel sends a ball bouncing around on the screen. Turn it into your own Pong, Breakout, or Tank clone.
To run this way, Threads are usually used to allow more than one thing to be going on at a time in a Java program. We've looked at a simple way of using threads before, the Timer class.
Here's a really, really simple video game kernel. It has all the basic elements of a video game.
/* A simple video game style kernel by Mark Graybill, August 2010 Uses the Timer Class to move a ball on a playfield. */ // Import Timer and other useful stuff: import java.util.*; // Import the basic graphics classes. import java.awt.*; import javax.swing.*; public class VGKernel extends JPanel{ // Set up the objects and variables we'll want. public Rectangle screen, ball; // The screen area and ball location/size. public Rectangle bounds; // The boundaries of the drawing area. public JFrame frame; // A JFrame to put the graphics into. public VGTimerTask vgTask; // The TimerTask that runs the game. public boolean down, right; // Direction of ball's travel. // Create a constructor method that initializes things: public VGKernel(){ super(); screen = new Rectangle(0, 0, 600, 400); ball = new Rectangle(0, 0, 20, 20); bounds = new Rectangle(0, 0, 600, 400); // Give some starter values. 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(){ moveBall(); frame.repaint(); } } // 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 void moveBall(){ // Ball should really be its own class with this as a method. if (right) ball.x+=ball.width; // If right is true, move ball right, else ball.x-=ball.width; // otherwise move left. if (down) ball.y+=ball.height; // Same for up/down. else ball.y-=ball.width; if (ball.x > (bounds.width - ball.width)) // Detect edges and bounce. { right = false; ball.x = bounds.width - ball.width; } if (ball.y > (bounds.height - ball.height)) { down = false; ball.y = bounds.height - ball.height;} if (ball.x <= 0) { right = true; ball.x = 0; } if (ball.y <= 0) { down = true; ball.y = 0; } } public static void main(String arg[]){ java.util.Timer vgTimer = new java.util.Timer(); // Create a Timer. VGKernel panel = new VGKernel(); // Create and instance of our kernel. // Set the intial ball movement direction. panel.down = true; panel.right = true; // Set up our JFRame 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, 100); } }
This example can be expanded with methods to get control inputs, additional players on the playfield (like paddles), and logic to determine when someone scores.
The code here is far from perfect, but I've made some compromises to make things as simple as I could while still showing a full working example. Not that any code that runs and does what is supposed to is really bad, but there are other, better ways of doing this. But this works and is fairly easy to understand.
What the program does is create a JPanel that has an inner class (a class defined within itself) of VGTimerTask. The VGTimerTask is a kind of TimerTask, which can be scheduled to occur on a regular basis by a Timer. Since VGTimerTask is an inner class of VGPanel, it has access to all the members of VGPanel. This is critical. Without that, it wouldn't be able to access the ball and redraw the screen easily (it can still be done, but in a more complex way.)
Timer is a decent way of running a simple game, but more complex games should use some other timing mechanism. java.util.Timer is affected by a number of outside events, so to get smoother, more reliable timing you a timer like the one in the Java3D package would work better.
A Simple Improvement
There are many ways of improving on this basic example. One way that is very simple is to smooth the animation. The movement of the ball is pretty jerky. This is caused by both the distance that the ball moves each "turn", and by the time between screen updates. We can smooth out the animation by addressing both of these.
First, let's change moveBall() to shift the ball a smaller distance each time:
public void moveBall(){ // Ball should really be its own class with this as a method. if (right) ball.x+=ball.width/4; // If right is true, move ball right, else ball.x-=ball.width/4; // otherwise move left. if (down) ball.y+=ball.height/4; // Same for up/down. else ball.y-=ball.width/4; if (ball.x > (bounds.width - ball.width)) // Detect edges and bounce. { right = false; ball.x = bounds.width - ball.width; } if (ball.y > (bounds.height - ball.height)) { down = false; ball.y = bounds.height - ball.height;} if (ball.x <= 0) { right = true; ball.x = 0; } if (ball.y <= 0) { down = true; ball.y = 0; } }Now the ball is being moved only one quarter of its size each turn.
Next, change the Timer schedule to draw the screen every 20 milliseconds instead of every 100 milliseconds:
// Set up a timer to do the vgTask regularly. vgTimer.schedule(panel.vgTask, 0, 20);
Now you have a ball that moves a lot smoother.
I'll be expanding on this basic kernel and improving it in future articles, starting with Java Video game Programming: Game Logic
Labels:
application,
graphics,
inner class,
JFrame,
JPanel,
loop,
paintComponent(),
threads

Friday, August 14, 2009
Java 3D Graphics Options
There are several approaches to doing 3-D graphics with Java. Unfortunately, there is no "standard" way. The core of Java does not include 3D graphics in the current versions (Java SE 5 and 6). The upcoming new version (SE 7) also does not, though it is intended to include a modular system that will download Java components that aren't already on a system as they are required. Chances are the major Java 3D APIs will take advantage of this.
Ways to Get 3-D Graphics in a Java Program:
1. Code It Yourself
You can write your own 3D graphics routines in standard Java. This avoids the need for those who run your programs to get add-ons to their Java to run your programs. It also means you'll really know what's going on in your 3D code.
However, this probably won't be an effective technique for you if you want to write programs with very sophisticated 3D in them, or need high performance.
2. JOGL
JOGL is a low-level set of APIs for accessing OpenGL on the system the program is running on. Runescape uses it. If you want to learn how to program 3-D the way most of the pros do it, and aren't afraid of having to learn all sorts of technical 3D graphics stuff to get there, then JOGL may be for you.
If you want to stick to a Java-like object oriented way of thinking, or don't want to delve too deeply into the underlying 3D graphics technology just to get a picture on-screen, then JOGL is probably not for you.
3. LWJGL
Another acronym, another low-level library like JOGL. LWJGL is oriented toward game development, including support for hardware like gamepads and controllers in addition to 3D graphics support. With respect to graphics, it has the same advantages and disadvantages as JOGL.
If I were going to start using the other capabilities of LWJGL right away, I'd start with it rather than JOGL. If I were focused on learning 3D graphics programming with OpenGL first, for example using the "Red Book" for OpenGL, I'd start with JOGL then move over to LWJGL if I felt it would be helpful.
4. Java3D
This is a high-level Java API that uses an object-oriented way of doing 3D graphics. It sticks with the same approach to doing things as the rest of Java. It lets you easily create 3D objects and set them up in scenes for display. If you're entirely new to 3D this is probably the place to start learning.
To use it, you need to install it on your system. Also, anyone who wants to run your Java3D programs will need to have it, too.
Java 3D binaries for different computer systems are available for download.
A good community site for further information on doing 3-D graphics with Java--no matter how you want to do them--is j3d.org.
Ways to Get 3-D Graphics in a Java Program:
1. Code It Yourself
You can write your own 3D graphics routines in standard Java. This avoids the need for those who run your programs to get add-ons to their Java to run your programs. It also means you'll really know what's going on in your 3D code.
However, this probably won't be an effective technique for you if you want to write programs with very sophisticated 3D in them, or need high performance.
2. JOGL
JOGL is a low-level set of APIs for accessing OpenGL on the system the program is running on. Runescape uses it. If you want to learn how to program 3-D the way most of the pros do it, and aren't afraid of having to learn all sorts of technical 3D graphics stuff to get there, then JOGL may be for you.
If you want to stick to a Java-like object oriented way of thinking, or don't want to delve too deeply into the underlying 3D graphics technology just to get a picture on-screen, then JOGL is probably not for you.
3. LWJGL
Another acronym, another low-level library like JOGL. LWJGL is oriented toward game development, including support for hardware like gamepads and controllers in addition to 3D graphics support. With respect to graphics, it has the same advantages and disadvantages as JOGL.
If I were going to start using the other capabilities of LWJGL right away, I'd start with it rather than JOGL. If I were focused on learning 3D graphics programming with OpenGL first, for example using the "Red Book" for OpenGL, I'd start with JOGL then move over to LWJGL if I felt it would be helpful.
4. Java3D
This is a high-level Java API that uses an object-oriented way of doing 3D graphics. It sticks with the same approach to doing things as the rest of Java. It lets you easily create 3D objects and set them up in scenes for display. If you're entirely new to 3D this is probably the place to start learning.
To use it, you need to install it on your system. Also, anyone who wants to run your Java3D programs will need to have it, too.
Java 3D binaries for different computer systems are available for download.
A good community site for further information on doing 3-D graphics with Java--no matter how you want to do them--is j3d.org.
Labels:
API,
graphics,
Java version

Friday, June 19, 2009
Greenfoot Results
I've posted an entry on my general blog about the results I saw from a semester with Greenfoot.
While Greenfoot was not as smooth and easy to use for beginners as I could hope, it was still a very valuable tool for the class. Both it and BlueJ are excellent ways of being introduced to some of the basic concepts behind object-oriented programming. Objects, inheritance, members, etc. are all right there for you to see and interact with, which does a heck of a lot for making things clearer.
I'd like to see BlueJ's codepad come over into Greenfoot. The student I had in individual study using BlueJ and Objects First as a text got a lot out of the codepad.
I'm planning on spending more time with Greenfoot soon, to get a better idea of what could have been done to successfully implement ideas from class that didn't work out. We had our share of frustrations, but at this point I couldn't say whether they were the result of our shortcomings or opportunities for Greenfoot to improve.
Check out the post linked above. The student all got their games in a playable state and posted at the Greenfoot Gallery, which is a huge axchievement (I did not expect 100% success on that count!) They're linked, as are the students' development blogs.
While Greenfoot was not as smooth and easy to use for beginners as I could hope, it was still a very valuable tool for the class. Both it and BlueJ are excellent ways of being introduced to some of the basic concepts behind object-oriented programming. Objects, inheritance, members, etc. are all right there for you to see and interact with, which does a heck of a lot for making things clearer.
I'd like to see BlueJ's codepad come over into Greenfoot. The student I had in individual study using BlueJ and Objects First as a text got a lot out of the codepad.
I'm planning on spending more time with Greenfoot soon, to get a better idea of what could have been done to successfully implement ideas from class that didn't work out. We had our share of frustrations, but at this point I couldn't say whether they were the result of our shortcomings or opportunities for Greenfoot to improve.
Check out the post linked above. The student all got their games in a playable state and posted at the Greenfoot Gallery, which is a huge axchievement (I did not expect 100% success on that count!) They're linked, as are the students' development blogs.

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.
Most of this program is the same as our previous one. There are a couple of significant changes, however.
One is the following line:
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
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:
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.
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.

Saturday, February 14, 2009
Better 2D Graphics: Java2D
In our last program we loaded and displayed an image using Java. Not only that, but we scaled it to be a specific size. We did this using the Image class from the java.awt package.
Unfortunately, this pretty well covers the abilities of the Image class. But there's so much more that we'd like to do with images in our programs, especially if we're writing games. Fortunately, there's more that Java can do with images thanks to Java2D.
If you go to the Java API you won't see a specific package called something like java.java2d or javax.swing.java2d. "Java2D" is a whole bunch of packages and classes spread through Java's libraries of stuff. The java.awt.image package is part of Java2D, as is the java.awt.Graphics2D class inside the java.awt package. For a list of all the scattered components of Java that are part of Java2D, have a look at the Java2D API Specification.
Like so much of Java, the presentation of Java2D is confusing. It's made to sound like a single thing when it's a bunch of interrelated things worked into Java. Fortunately, like many such problems in understanding Java, it's only a problem of how the language is presented, not a problem with the language itself. Once you get to working with the elements of Java2D, you find that they're fairly naturally positioned in the places you would expect them in Java by their function. Which is how they got spread out in the first place (that and some history--it would have been even more natural to have there be one Graphics class that does everything, rather than a Graphics and Graphics2D class.)
Also, it's very easy to take items that are non-Java2D classes and use them with Java2D. Usually it's nothing worse than "casting" them as Java2D objects. That means you basically tell Java "pretend this object is the right sort of thing" in a way that works.
So have a look at some info on Java2D, and if it looks confusing, remember it's not you that's the problem. Sun does an amazing job of presenting great things in awful ways by trying to say way too much to too many different audiences at once. And they like to start in the middle of the story.
The Java2D tutorials do a decent job of showing things off without a lot of mind-numbing prose (well, not too much, anyway.)
Next I'll post a short, simple program we can use that rotates our images.
Unfortunately, this pretty well covers the abilities of the Image class. But there's so much more that we'd like to do with images in our programs, especially if we're writing games. Fortunately, there's more that Java can do with images thanks to Java2D.
If you go to the Java API you won't see a specific package called something like java.java2d or javax.swing.java2d. "Java2D" is a whole bunch of packages and classes spread through Java's libraries of stuff. The java.awt.image package is part of Java2D, as is the java.awt.Graphics2D class inside the java.awt package. For a list of all the scattered components of Java that are part of Java2D, have a look at the Java2D API Specification.
Like so much of Java, the presentation of Java2D is confusing. It's made to sound like a single thing when it's a bunch of interrelated things worked into Java. Fortunately, like many such problems in understanding Java, it's only a problem of how the language is presented, not a problem with the language itself. Once you get to working with the elements of Java2D, you find that they're fairly naturally positioned in the places you would expect them in Java by their function. Which is how they got spread out in the first place (that and some history--it would have been even more natural to have there be one Graphics class that does everything, rather than a Graphics and Graphics2D class.)
Also, it's very easy to take items that are non-Java2D classes and use them with Java2D. Usually it's nothing worse than "casting" them as Java2D objects. That means you basically tell Java "pretend this object is the right sort of thing" in a way that works.
So have a look at some info on Java2D, and if it looks confusing, remember it's not you that's the problem. Sun does an amazing job of presenting great things in awful ways by trying to say way too much to too many different audiences at once. And they like to start in the middle of the story.
The Java2D tutorials do a decent job of showing things off without a lot of mind-numbing prose (well, not too much, anyway.)
Next I'll post a short, simple program we can use that rotates our images.

Monday, January 26, 2009
Loading and Displaying an Image in Java
Here's a common task--loading an image file and displaying it in a window.
I'll be using this program as a basis for further two dimensional graphics exercises, so give it a try and play around with it.
First, we need to get a picture to use. I use a picture of Duke, the Java mascot, from https://duke.dev.java.net/images/web/Duke_Blocks.gif
If you want to run the program as I present it, download the image and save it into the same directory that yor java program will be in. If you want to use your own image, replace the file name Duke_Blocks.gif with the name of your image file, and make sure the image is in the same directory as your java program.
The only somewhat tricky part is that we're using a Toolkit method to get the image. Take a look at the Java API reference to learn more about the Toolkit. (The Toolkit object is part of the java.awt package. So select "java.awt" in the top left frame of the API reference webpage to make finding Toolkit in the lower left frame easier.)
In this program, we scale and position the image in our window. In future programs, we'll convert the image to a Java2D object (which is really easy) so that we can do other things, like rotate it and use it as a sprite.
Here's the program:
I'll be using this program as a basis for further two dimensional graphics exercises, so give it a try and play around with it.
First, we need to get a picture to use. I use a picture of Duke, the Java mascot, from https://duke.dev.java.net/images/web/Duke_Blocks.gif
If you want to run the program as I present it, download the image and save it into the same directory that yor java program will be in. If you want to use your own image, replace the file name Duke_Blocks.gif with the name of your image file, and make sure the image is in the same directory as your java program.
The only somewhat tricky part is that we're using a Toolkit method to get the image. Take a look at the Java API reference to learn more about the Toolkit. (The Toolkit object is part of the java.awt package. So select "java.awt" in the top left frame of the API reference webpage to make finding Toolkit in the lower left frame easier.)
In this program, we scale and position the image in our window. In future programs, we'll convert the image to a Java2D object (which is really easy) so that we can do other things, like rotate it and use it as a sprite.
Here's the program:
/* ShowImage.java
This program loads and displays an image from a file.
mag-13May2008
updated 20Feb2009 by mag to incorporate suggestions
by mazing and iofthestorm on digg.
*/
// Import the basic graphics classes.
import java.awt.*;
import javax.swing.*;
public class ShowImage extends JPanel{
Image image; // Declare a name for our Image object.
// Create a constructor method
public ShowImage(){
super();
// Load an image file into our Image object.
// This file has to be in the same
// directory as ShowImage.class.
image = Toolkit.getDefaultToolkit().getImage("Duke_Blocks.gif");
}
// The following methods are instance methods.
/* Create a paintComponent() method to override the one in
JPanel.
This is where the drawing happens.
We don't have to call it in our program, it gets called
automatically whenever the panel needs to be redrawn,
like when it it made visible or moved or whatever.
*/
public void paintComponent(Graphics g){
// Draw our Image object.
g.drawImage(image,50,10,200,200, this); // at location 50,10
// 200 wide and high
}
public static void main(String arg[]){
JFrame frame = new JFrame("ShowImage");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600,400);
ShowImage panel = new ShowImage();
frame.setContentPane(panel);
frame.setVisible(true);
}
}

Tuesday, January 13, 2009
Listeners: Can Java Hear You?
In the program given in Simple Mouse Interaction in Java we used a Listener to connect our program to the mouse. We were able to use the Listener to find out when and where the mouse had been clicked within our program's window. We used this information to draw lines in the window, in a similar fashion to our earlier programs but controlled by the mouse, rather than from specific drawing instructions in the program that do the same thing every time you run the program.
By implementing the MouseListener interface, we were able to talk to the mouse very easily. However, a MouseListener is just one of the many types of Listener available in Java.
What Sort of Listener Are You?
If we tried to implement a full graphical interface in a program by using MouseListener, we'd have a lot of work to do. We'd have to draw all the buttons using drawing instructions in our program, then wait for mouse clicks. Once we got a click on something we'd have to figure out what had been clicked on by the location of the click in our window. Then we'd have to redraw the button (or slider, or whatever) to show that it had been clicked. Then we'd have to continue responding to the mouse by figuring out what the user is doing (clicking and releasing, clicking and dragging, or what) and make our program and the picture on the screen respond appropriately.
Whew! What a lot of work that would be! If we had to do that it'd almost be enough to drive you back to the command line. (Once upon a time you did have to do all that, believe it or not. Thank goodness those days are gone.)
Fortunately, Java has a number of different types of Listener suited for different tasks that take care of the complexity for you, and let your program do what you want it to do without you having to spell out every little detail. There are listeners for buttons, sliders and other controls such as trees, lists, focus changes, and so on. You can also write your own Listeners, so that you can create a new type of control and only ever have to deal with the inner complexities of how it works once.
What is a Listener?
A Listener is a connection between your program and something that creates an Event. An Event is a communication from a device on the computer or a program to something outside itself on the computer, like another program or device (through a program associated with that device, like its device driver.) In the case of our mouse program, the Listener is the connection between the mouse's button and our program. Whenever the left button is clicked, an Event is generated that contains what happened (a left-click) and the location in our window where it happened.
If the click happens outside our program's window, an Event is generated, but our program isn't included in the recipients of the message. If our program doesn't have a Listener, the mouse click Event gets passed to our program but is ignored.
If we have a Listener appropriate to an Event that's passed to our program, then something happens with it. So we have to create a Listener, tell our program to add it to its list of Listeners (which also tells the program what kind of events it's listening for.) Then our program will tell that Listener whenever one of those events happens, and pass along the details.
A MouseListener is a very generalized sort of Listener. An ActionListener, however, can be set up to listen for a specific event, like a click on a specific button. Take a look in the Java API at ActionListener. By associating an ActionListener with a specific button, you can hear only about when that button is clicked, and know that that's precisely what happened. That ActionListener won't hear about clicks elsewhere, you don't need to check the location of the click, and it won't tell you about anything else you don't want to hear about.
That saves you all the trouble that I talked about above. You can set up your ActionListener to just exeecute the part of your code you want it to run when someone clicks the button. Or slides the slider, or whatever. No fuss, no muss.
I'll be posting a sample program soon, until then have a look at the Sun Java Tutorials on using buttons and other controls from Swing (Java's best set of graphical user interface objects.)
By implementing the MouseListener interface, we were able to talk to the mouse very easily. However, a MouseListener is just one of the many types of Listener available in Java.
What Sort of Listener Are You?
If we tried to implement a full graphical interface in a program by using MouseListener, we'd have a lot of work to do. We'd have to draw all the buttons using drawing instructions in our program, then wait for mouse clicks. Once we got a click on something we'd have to figure out what had been clicked on by the location of the click in our window. Then we'd have to redraw the button (or slider, or whatever) to show that it had been clicked. Then we'd have to continue responding to the mouse by figuring out what the user is doing (clicking and releasing, clicking and dragging, or what) and make our program and the picture on the screen respond appropriately.
Whew! What a lot of work that would be! If we had to do that it'd almost be enough to drive you back to the command line. (Once upon a time you did have to do all that, believe it or not. Thank goodness those days are gone.)
Fortunately, Java has a number of different types of Listener suited for different tasks that take care of the complexity for you, and let your program do what you want it to do without you having to spell out every little detail. There are listeners for buttons, sliders and other controls such as trees, lists, focus changes, and so on. You can also write your own Listeners, so that you can create a new type of control and only ever have to deal with the inner complexities of how it works once.
What is a Listener?
A Listener is a connection between your program and something that creates an Event. An Event is a communication from a device on the computer or a program to something outside itself on the computer, like another program or device (through a program associated with that device, like its device driver.) In the case of our mouse program, the Listener is the connection between the mouse's button and our program. Whenever the left button is clicked, an Event is generated that contains what happened (a left-click) and the location in our window where it happened.
If the click happens outside our program's window, an Event is generated, but our program isn't included in the recipients of the message. If our program doesn't have a Listener, the mouse click Event gets passed to our program but is ignored.
If we have a Listener appropriate to an Event that's passed to our program, then something happens with it. So we have to create a Listener, tell our program to add it to its list of Listeners (which also tells the program what kind of events it's listening for.) Then our program will tell that Listener whenever one of those events happens, and pass along the details.
A MouseListener is a very generalized sort of Listener. An ActionListener, however, can be set up to listen for a specific event, like a click on a specific button. Take a look in the Java API at ActionListener. By associating an ActionListener with a specific button, you can hear only about when that button is clicked, and know that that's precisely what happened. That ActionListener won't hear about clicks elsewhere, you don't need to check the location of the click, and it won't tell you about anything else you don't want to hear about.
That saves you all the trouble that I talked about above. You can set up your ActionListener to just exeecute the part of your code you want it to run when someone clicks the button. Or slides the slider, or whatever. No fuss, no muss.
I'll be posting a sample program soon, until then have a look at the Sun Java Tutorials on using buttons and other controls from Swing (Java's best set of graphical user interface objects.)

Monday, August 11, 2008
Simple Mouse Interaction in Java
Building on the basic graphics we've done in Very Basic Java Graphics--3 Examples and A Most Basic Graphics App we'll be adding mouse interaction in this example.
To add mouse interaction, we're taking advantage of an interface from the
Implementing the
This program lets you draw by clicking the mouse at various places in the MousePanel's drawing area, drawing a line from the prior click location (or from top left for the first click) to the location of the current click.
Here's a little challenge for you:
Change the program so that it doesn't draw a line from upper left on the first click, but instead draws a dot in the location of the first click. Later clicks will then draw lines from the prior click's location.
Hint: If you set the initial oldX and oldY values to a value that isn't in the visible MousePanel area, you can tell if there haven't been any prior clicks.
/* MousePanel.java
This program adds the ability to respond to
mouse events to the BasicPanel program.
The mouse clicks are used to draw on the
panel area using drawline instructions.
mag-30Apr2008
*/
// Import the basic necessary classes.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MousePanel extends JPanel implements MouseListener{
public MousePanel(){
super();
pointX=20;
pointY=20;
oldX=0;
oldY=0;
addMouseListener(this);
}
int pointX, pointY, oldX, oldY;
public void paintComponent(Graphics g){
// Draw a line from the prior mouse click to new one.
g.drawLine(oldX,oldY,pointX,pointY);
}
public void mouseClicked(MouseEvent mouse){
// Copy the last clicked location into the 'old' variables.
oldX=pointX;
oldY=pointY;
// Get the location of the current mouse click.
pointX = mouse.getX();
pointY = mouse.getY();
// Tell the panel that we need to redraw things.
repaint();
}
/* The following methods have to be here to comply
with the MouseListener interface, but we don't
use them, so their code blocks are empty. */
public void mouseEntered(MouseEvent mouse){ }
public void mouseExited(MouseEvent mouse){ }
public void mousePressed(MouseEvent mouse){ }
public void mouseReleased(MouseEvent mouse){ }
public static void main(String arg[]){
JFrame frame = new JFrame("MousePanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(250,250);
MousePanel panel = new MousePanel();
frame.setContentPane(panel);
frame.setVisible(true);
}
}
To add mouse interaction, we're taking advantage of an interface from the
java.awt.events
package called MouseListener. When we implement MouseListener as part of our JPanel class, then call addMouseListener(this)
as part of our MousePanel()
constructor, our program is "wired up" to the mouse, so that our MousePanel gets mouse events from the JVM.Implementing the
MouseListener
interface requires that we implement all the methods called for by the interface. We only use MouseClicked()
in this example, however, so it's the only one that has code in its code block.This program lets you draw by clicking the mouse at various places in the MousePanel's drawing area, drawing a line from the prior click location (or from top left for the first click) to the location of the current click.
Here's a little challenge for you:
Change the program so that it doesn't draw a line from upper left on the first click, but instead draws a dot in the location of the first click. Later clicks will then draw lines from the prior click's location.
Hint: If you set the initial oldX and oldY values to a value that isn't in the visible MousePanel area, you can tell if there haven't been any prior clicks.

Subscribe to:
Posts (Atom)
Subjects:
- Android (3)
- angle brackets (1)
- API (15)
- applet (2)
- application (15)
- arguments (2)
- array (3)
- array initializer (1)
- assignment (3)
- asterisk (2)
- beginner (8)
- book review (4)
- C (1)
- C# (1)
- C++ (1)
- calculations (4)
- classes (8)
- code blocks (3)
- collection (6)
- collision detection (3)
- command line (7)
- Comments (1)
- comparison (3)
- constants (1)
- constructor (2)
- cross-platform (1)
- curly braces (3)
- dates (1)
- declaration (4)
- documentation (3)
- dot notation (1)
- embedded (1)
- environment (11)
- equals (2)
- events (3)
- example (2)
- expressions (2)
- file (3)
- file names (1)
- framework (3)
- generics (2)
- graphics (22)
- graphics Swing CSS (1)
- heavyweight component (1)
- humor (1)
- i/o (3)
- IDE (9)
- import (2)
- inheritance (2)
- initializer (1)
- inner class (5)
- input (5)
- interface (3)
- Java (27)
- Java version (7)
- Javascript (1)
- JDK (5)
- JFrame (6)
- JPanel (7)
- JVM (10)
- lightweight component (2)
- List (3)
- listeners (3)
- literal (1)
- local (1)
- loop (2)
- main() (4)
- Math (3)
- method (4)
- methods (2)
- modulo (1)
- mouse (1)
- name (2)
- numeric (2)
- object code (1)
- objects (3)
- operators (4)
- output (3)
- packages (5)
- paint() (3)
- paintComponent() (4)
- parentheses (1)
- percent sign (2)
- PHP (1)
- public (2)
- read (2)
- reference (8)
- regular expressions (1)
- Resources (5)
- restore (1)
- save (1)
- Scanner (1)
- semicolons (1)
- signature (4)
- source code (4)
- square brackets (1)
- star (1)
- static (2)
- Swift (1)
- System.out.println() (2)
- threads (2)
- trigonometry (1)
- type (8)
- variables (9)
- video game (8)
- virtual machine (2)
- void (2)
- web (2)
- why java (9)