Interesting Technology

Describes different types of things I find interesting.

Wednesday, August 26, 2009

Setup and Use JGame in Netbeans

JGame Tutorial

This was a tutorial I put together for a class I taught. It has references to a project we did in the course, but it has useful general information about setting up and using the basic features of JGame in Netbeans. If you have questions about feel free to email me.

Downloading
Setting up Netbeans
Using the Engine
Understanding Game States
Handling Keyboard input
Objects and Collisions
Using Media


Downloading
To download JGame go to http://www.13thmonkey.org/~boris/jgame/
Download the ZIP (Windows) or tar.gz file (Unix/Mac).
Expand the files into a directory
Move on to setup in Netbeans now!

Setting up Netbeans
To setup JGame in Netbeans you should create a Library. Libraries let you share external code libraries among many projects in Netbeans very easily.

Creating the JGame Library in Netbeans
  1. Go to Tools->Libraries
  2. Click on "New Library"
  3. Enter a name "Jgame" for example, select "Class Library" from the drop-down menu if it is not already selected.
  4. Press "Ok" (on Mac possibly "Apply" on Windows)
  5. Select the "Classpath" tab
  6. Click "Add Jar/Folder"
  7. Navigate to the folder where you installed JGame and select the Jar file: jgame-all.jar
  8. Click on the "Sources" tab
  9. Click "Add Jar/Folder"
  10. Navigate to the folder where you installed JGame and select the directory: src-base and click "Add Jar/Folder"
  11. Repeat steps 9-10 for other source directories in JGame: src-jogl, src-midp
  12. Click the Javadoc tab
  13. Navigate to the folder where you installed JGame and select the directory: javadoc and click "Add Jar/Folder"
  14. Now click "Okay" and the Library Manager should close.
Using the Library in your project
To use the JGame library (or any library) you must add it into your Netbeans project. To do that:
  1. Open an existing project or create a new project
  2. Click on the Projects tab (usually in the left window in Netbeans
  3. Right-click on your project name and select "Properties"
  4. Click "Libraries"
  5. Make sure the "Compile" tab is selected (it should be by default)
  6. Click "Add Library"
  7. Choose JGame
  8. Click Okay
Now you can use any of the resources in the JGame library in this project and Netbeans will know about them! You can also right-click on a JGame class and view Javadocs for that class. Try it by creating a new class and type in JGEngine. Then right-click on the text and choose Javadocs.
Using the Engine
The engine is the class in JGame the you'll use to control states and manage the whole process of the game. You'll want to create your own class for this project that extends the JGEngine class (so you get all the wonderful capabilities of the engine!)

public class JMortarEngine extends JGEngine {
...
}


There are many methods in this class you will use. Some important ones are:
initGame --- called to initialize anything you need to setup before the game starts
initCanvas --- called to setup the drawing surface the game will use.

Here are the methods I used... feel free to copy them :-)

@Override
public void initCanvas() {
// An 800x600 window is what we want
setCanvasSettings(800, 600, 1, 1, JGColor.black, JGColor.white, null);
}

@Override
public void initGame() {
setFrameRate(35, 2);
defineMedia("media.tbl"); // Load in the media we'll use for the game.
}

Some more help to get you started is what to do in the constructor. Here's what I did:

public JMortarEngine(GameState gameState, int width, int height) {
// Call the constructor from the original JGEngine class to
// make sure it sets everything up
super();


// Hold onto a reference to the GameState object from Lab3.
// This is the panel that will be at the bottom of the screen
// Why? So you can call methods on it

// like gameState.updatePlayer1Score(), etc...
this.gameState = gameState;

dbgShowBoundingBox(false); // Helpful to see bounding boxes sometimes
dbgShowGameState(true); // Helpful to see the game state sometimes

initEngine(width, height);
setSize(new Dimension(width, height));
setGameState("Start"); // Transition to the "Start" state as the first state in the game.
}


Other things:
engine.pfWidth() and engine.pfHeight() will return the width and height of the playing area. This is useful many times to calculate positions of things on the screen. (Note for later use outside this CS class: tile widths can mess this up. Our tile width is 1 so we're good, but be careful if you use JGame for another project.)


Understanding Game States

Game states are used throughout JGame to manage what is happening in the game. During different states you can draw different things on the screen and process frames in different ways.

For example, in the "Title" state you may just want to put information on the screen saying "Get ready!!!" but in the "Firing" state you must draw the mortar (bullet) on the screen and move it appropriately every time a new frame is requested.

Each state has special methods. Lets say you have a state called "Title", then the game engine will AUTOMATICALLY call the following methods for you:

public void startTitle()
public void paintFrameTitle()
public void doFrameTitle()

You must define these in your JMortarEngine class (your subclass of JGEngine). Once they are defined the engine will automatically call them once the Title state is entered. You can define any state name you want, and then create methods:


public void startYOUR_STATE_NAME()
public void paintFrameYOUR_STATE_NAME()
public void doFrameYOUR_STATE_NAME()

The startXXX is called when the engine first enters the state. This is useful when you need to create new objects (like mortar bullets) at the beginning of a state.

The paintFrameXXX method is called to let you draw something on the screen.

The doFrameXXX method is called to let you process things that may have happened. This is where you'll get the most recent key the user pressed and do something about it. Usually transition to another state, check for bullet collisions, update the scores, etc...

All of these methods are optional, and if they don't exist they just won't be called. Remember though, you need a way to exit a state and go into the next state!

To change from one state to another you should remove the current state and add the next state:
removeGameState("Title");
addGameState("Player1");

You can also do it with a timer:
public void startTitle() {
new JGTimer(30, true) {
// the alarm method is called when the timer ticks to zero
public void alarm() {
removeGameState("Title");
addGameState("Firing");
}
};
}

Game states are crucial to JGame. Depending on the state you're in, the game will do very different things.

Handling Keyboard input
The engine can determine the last key pressed using:

int key = getLastKey();

The "key" variable is then set to the Unicode value for the key that was pressed.

Once you handle the key-press you want to clear it so you don't handle it again. Otherwise, if you never clear the key, once the user presses a key you'll ALWAYS get that key from getLastKey() until they press another key. Probably not what you want for JMortarWar, but for Pacman that could be exactly what you want.

Objects and Collisions

For JGame most things on the screen will be JGObjects. For example the "Hill" is defined as:
public class Hill extends JGObject

By making everything a JGObject you get all the methods of JGObjects (which are very useful). Some of the most useful for you are:
  • setImage(String imgName) // Set the image used to display this object (image must be loaded from the media table first!). But that is usually done during initialization of the engine
  • setPos(int x, int y) // Sets the location of this object on the screen.
  • move() // Update the position of the mortar round in here using setPos
  • getBBox() // Used to find the bounding box of the Object. Good for positioning the tank's turret in the middle of the tank
  • hit(JGObject obj) // This method is called when another JGObject hits you. So, when the tank gets hit, you probably want to play the explosion sound here.
  • remove() // Remove this object from the screen
  • paint() // override this to paint yourself. You'll use this to paint the turret on the screen (it's just a 4 pixel wide line)
  • isAlive() // This method will tell you if an object is still alive or not. To use this, just make sure you remove the mortarrounds if they hit something. A removed mortarRound will return "false" from isAlive(). Thus, when both mortarrounds are not alive, you can move on to the next state.
Collision IDs and collision checking
Every type JGObject has a collision ID that is used to determine if it can hit something else. Collision IDs are used to determine what types of objects can collide with each other. In our system everything collides with everything (because we only have hills, tanks, turrets, and mortar rounds)

In the constructor for your JGObject, you normally call the super-class (parent's) constructor with something like this:
// Initialize game object by calling an appropriate constructor
// in the JGObject class.
super(
"hill",// name by which the object is known
true, //true means add a unique ID number after the object name.
//If we don't do this, this object will replace any object
//with the same name.
engine.pfWidth() / 2, // X position
engine.pfHeight() / 2, // Y position (0=top of the screen)
2, // the object's collision ID (used to determine which classes
// of objects should collide with each other)
null, // name of sprite or animation to use (null is none)
JGObject.expire_off_view);

So for all Hill objects, they have a collision ID of 2. To determine if a bullet hit the Hill you would need to call in one of the doFrameXXX states:
checkCollision(4, 2); // Where 4 is the collision ID of the bullet.

If the bullet did hit the bounding box of the hill, then the hit() method of the hill will be called because the hill's ID is the second parameter to checkCollision. The second collision ID is the one that gets the hit() method called. So, the hill must decide what to do when a bullet hits it.

Another way to check for collisions is to use:

int cids = checkCollision(cid, JGObject);
For example:
int cids = checkCollision(4, player1);

This will return the bitwise "OR" of player1's cid and 4 (the first parameter) if they hit, otherwise it'll return 0. So, the easiest thing to do in our scenario is just check for any non-zero return value and that means that the bullet hit the player. Using this form of checkCollision does NOT call the hit() methods though. You'll need to do that manually if you use this method to check for collisions!

Using Media

To use media in JGame requires having a media description file that shows where the media is relative to your root directory. Some specific steps to set this up to use the media table I'll give you:
  1. Right-click on your jmortarwar package
  2. Select New->Java Package
  3. Add the media package as: jmortarwar.media
  4. Press "Okay"
Now, in the project information on the left of the screen you should see a "jmortarwar.media" package. Drag and drop all the media files (JPGs, PNGs, GIFs, WAVs, etc...) into that package.

Drop the media.tbl file into the jmortarwar package. This file gives names to the media and also creates different versions for the tank (a version that points left and right). Be very careful the media.tbl file requires tab characters. If you edit that file with Netbeans it may convert the tabs to spaces and break your file!

Download the JAR resources for the project.

Once you have these files correctly installed you may "load" the media like this:
  1. In your engine class call: defineMedia("media.tbl"); during initialization
  2. In JGObject classes you can: setImage("mortarround");
  3. In your engine class you can : playAudio("explosion");

Sunday, August 23, 2009

Mac PowerPoint Scripting

Scripting in PowerPoint can help automate most repetitive tasks. The example script here will automatically go through all your slides and add a footer that gives the title of the next slide coming up. This helps during a presentation because you can see what's coming and transition well to the next slide.

A future blog post will show a PowerPoint script I use to add a progress bar showing the remaining slides.

Warning: This example is specific to Mac and uses AppleScript. It will not work on Windows. Windows PowerPoint scripting is done in VBA, not AppleScript.

For those in a hurry (or who have coded before), here is all the code:

tell application "Microsoft PowerPoint"

set oPres to active presentation

set mySlide to 1

tell active presentation to set currentSlide to slide mySlide

set titleTypes to {placeholder type title placeholder, placeholder type center title placeholder, placeholder type vertical title placeholder}

set footerTypes to {placeholder type footer placeholder}

repeat with currentSlide in (get every slide of oPres)

if mySlide > 1 then

-- Get the title of the current slide

repeat with i from 1 to count shapes of currentSlide

set currentShape to shape i of currentSlide

set aType to placeholder type of currentShape

if aType is not missing value and aType is in titleTypes then set myTitle to currentShape

end repeat

-- Get the footer of the previous slide

repeat with i from 1 to count shapes of prevSlide

set currentShape to shape i of prevSlide

set aType to placeholder type of currentShape

if aType is in footerTypes then set myFooter to currentShape

end repeat

-- Set the previous slide footer text to current's title

set prevSlide to mySlide - 1

set fText to "Coming up: " & content of text range of text frame of myTitle

set header footer text of footer of headers and footers of slide prevSlide of active presentation to fText

end if

set prevSlide to currentSlide

set mySlide to mySlide + 1

end repeat

set mySlide to mySlide - 1

set header footer text of footer of headers and footers of slide mySlide of active presentation to "End of presentation"

return currentSlide

end tell


To use this code open Script Editor.app

  1. Choose File->New
  2. Paste all the code in the window
  3. Save the file as: Documents/Microsoft User Data/PowerPoint Script Menu Items/addNextSlideFooter.scptd
  4. Open a PowerPoint presentation
  5. Ensure that footers are being shown (if they aren't just add a footer with any text in it. This script will REPLACE the footer text)
  6. Choose the automator menu (squiggly option to the right of Help)
  7. Choose the name of your script (addNextSlideFooter.scptd)
This has worked for me on PowerPoint 2008 on Mac OSX. This will NOT work on Windows! If you write the same script for Windows in VBA let me know and I'll link it here.

Same code with more details (in red)


tell application "Microsoft PowerPoint" -- This just tells the script we're using PowerPoint

-- set X to Y just sets a variable. Similar to x = y in other languages.

set oPres to active presentation

set mySlide to 1

tell active presentation to set currentSlide to slide mySlide

-- We need to create a list of types that could possibly hold the title so we can get the title later.

-- Luckily, if you're using a PowerPoint template there are some specific title placeholders.

-- If you aren't using a template (or any of these placeholders) for the title, this whole script won't work.

set titleTypes to {placeholder type title placeholder, placeholder type center title placeholder, placeholder type vertical title placeholder}

set footerTypes to {placeholder type footer placeholder}



-- Loop over all slides in the presentation, setting currentSlide to the current slide in each loop.

repeat with currentSlide in (get every slide of oPres)


-- We set the title of the previous slide, so if we're on slide 1, skip it!

if mySlide > 1 then

-- Get the title of the current slide by searching all the shapes for one of

-- the correct type.

repeat with i from 1 to count shapes of currentSlide

set currentShape to shape i of currentSlide

set aType to placeholder type of currentShape


-- If there is a title, store it in the variable myTitle

if aType is not missing value and aType is in titleTypes then set myTitle to currentShape

end repeat

-- Get the footer of the previous slide (same this as the title, but for the previous slide)

repeat with i from 1 to count shapes of prevSlide

set currentShape to shape i of prevSlide

set aType to placeholder type of currentShape

if aType is in footerTypes then set myFooter to currentShape

end repeat

-- Set the previous slide footer text to current's title

set prevSlide to mySlide - 1

set fText to "Coming up: " & content of text range of text frame of myTitle

set header footer text of footer of headers and footers of slide prevSlide of active presentation to fText

end if

set prevSlide to currentSlide -- Update some variables

set mySlide to mySlide + 1

end repeat


-- Make sure the last slide says "End of presentation" in the footer.

set mySlide to mySlide - 1

set header footer text of footer of headers and footers of slide mySlide of active presentation to "End of presentation"

return currentSlide

end tell -- DONE!


Followers

About Me

I am currently an instructor at George Mason University. I teach Computer Science and Software Engineering. My research focus is computer vision. In addition to my research in computer vision, I am interested in software engineering processes to help teams succeed in building software. I also enjoy building things from wooden furniture to robotics.