Jump to content
 Share

Joshy

Java in Eclipse and Programming with Graphics

Recommended Posts

Posted  Edited by Joshy

For starters and to be candid: This topic is not my strong point and my verbiage is weak.  My background is very hardware-oriented using code to control things and to interpret data.  Feel free to blast at it or to make suggestions.  I also want to give a special shout out to my sister for the programming inspiration.  My previous guides on programming were a great way to start walking and make some programming progress, but I understand that making text-based calculators and games can be less exciting.  The previous guide can be found in the thread below and covers functions, which will be used in this tutorial; it has links to prior threads if any further review may be helpful.

 

 

The next step is to begin using high-level object-oriented programming.  The goal here isn't so much to be the cleanest, the most efficient, prettiest neither the most intelligent approach.  Similar to the other guides: It's to help new users get started, but now we'll be jogging a little bit and it's up to the readers to run.  This guide will not be using Quincy like the other guide, but a lot of the strategies still work here ie. loops and conditional statements.  We'll be using Eclipse IDE for Java Developers.  The software may complain asking for a Virtual Machine.  I'm not a big fan of the virtual machine, and so I recommend installing the Java JDK.

 

There is a welcome screen to help new users become more acquainted with this IDE, and you can run through Create a Hello World application.  Most of this guide will literally walk you through their guide - not mine (I wont take credit for those parts) - but I noticed a few frustrating checkboxes that could be deal-breaking for new users.  I'll expand towards the end going beyond what they offer, and so I encourage the reader to follow through because the ending will contain what many learners have asked me (I think it will be interesting and it was certainly fun to fiddle with).

 

fYjcs00.png

 

You can follow the instructions on the right side.

 

It'll mention something about a Java perspective.  You should be able to skip this step because the default is Java perspective.  Eclipse has multiple "perspectives" kind of like modes or different viewers such as Debug.  More advanced users might be interested in using the Debug mode because it gives you a way to step through your code line by line, and you can see what's stored into your variables.  If you happen to not be on the Java perspective by default, then this is what you're looking for:

 

ikqkL4k.png

 

It'll ask you to start a Java project.  Click Next and uncheck the Create module-info.java file; otherwise you'll be frustrated by an error later, but you can still recover by deleting it.

 

nof177W.png

 

Next step is to create a new Class, and to check off using the main() method.

 

bPzsESH.png

 

 

It'll write the first few lines for you, but you'll have to add its print statement.  It's different than C or C++.

 

public class HelloWorld 
{

	public static void main(String[] args) 
	{
		// TODO Auto-generated method stub
		System.out.println("Hello world!");

	}

}

 

Now you can run this (you can either save first or it'll ask you to save when you Run as).  The results will be shown in the console on the bottom.

 

dboNjGe.png

 

onSDFkY.png

 

Let's get a tiny bit more fancy and take advantage of Java as opposed to what I had shown in C programming.  Next, download Objectdraw.  If it doesn't download automatically, then right click "save as" on the link.  It's suppose to be a .jar or .zip file.

 

Spoiler

Small note: The original link I used was http://eventfuljava.cs.williams.edu/library/ but last I checked the website was no longer working.  I'll leave it up in case it's up and running with a later version of Objectdraw.

 

You can save it wherever you would like, but you'll want to tell Eclipse where to find it.  Right click on your project and configure the build path.  Switch to libraries, click on Classpath, and add an external JAR and browse to where you've saved Objectdraw.

 

I06HAoZ.png

 

There's documentation for Objectdraw that'll look like the API for the code used in games.  You can Google it although I like the one from this class website.  The code will activate when certain events occur.  For example: For all commands that we'll want activating when the mouse moves, we'll put them inside of the following:

 

public void onMouseMove(Location point)
{
	// Put the commands here
}

 

There are many more such as the following, which can found under WindowController:

 

public void onMouseMove(Location point)
{
	// Put the commands in here
}
	
public void onMouseClick(Location point)
{
	// Put the commands in here
}
	
public void onMouseDrag(Location point)
{
	// Put the commands in here
}
	
public void onMouseExit(Location point)
{
	// Put the commands in here
}
	
public void onMouseRelease(Location point)
{
	// Put the commands in here
}

 

The overall code will require importing Objectdraw, and putting inside of the event onMouseMove a command like adding text.  Location point is (x, y) coordinates of where our cursor is.  We will also have to start a window controller to do all of this in, which I've placed into the main; the numbers that follow it is its width and height.

 

import objectdraw.*;

public class HelloWorld extends WindowController
{
	
	// Do something when the mouse moves
	public void onMouseMove(Location point)
	{
		new Text("Hello world!", point, canvas);
	}
	
	
	public static void main(String[] args) 
	{
		new HelloWorld().startController(400, 400);
	}

}

 

The outcome: It prints "Hello world!" when I move the mouse over the window controller.

 

1KrUKeC.png

 

The reason you see so many "Hello world!" is because it keeps creating a new "Hello world!" when I move the mouse, but we can clear the canvas using (admittedly not efficient but just for starters)

canvas.clear();

 

The object we want to explore is the text.  I can declare it kind of like a variable, and then I can apply other commands to the object.  You will use a similar format for all other objects.

// declaration
Text myText;

 

We can clear the canvas and do things to the objects.  In the case of text we can change its font size and colour.  Eclipse may give you hints as you're typing in the code.

// format is object.action(inputParameters)

// myText is the object and we want to set its font size to 30
myText.setFontSize(30);

// myText is the object and want to change its font color to red
myText.setColor(Color.red);

// myCircle is the object and I want to get its width
myCircle.getWidth();

 

The approach to this beyond the example code is looking for the types of classes you can work with from the Java documentation.  An example of FilledOval class you can see, in a sense, has a list of commands within it you can use on it; some classes share the same or similar commands you can use, but sometimes you cannot mix it.  Below we see 

 

XsTU5LH.png

 

// created myOval
myOval = new FilledOval(xLocation, yLocation, ovalWidth, ovalHeight, canvas);

// try something on it
myOval.getHeight();
myOval.moveTo(xLocation2, yLocation2);

// This wont work because it's not available in FilledOval (even though it is in Text)
myOval.setItalic() // DOES NOT WORK
  
// Try it for a text object now
myText = new Text("Example text", xLocation, yLocation, canvas);
myText.setItalic();

 

The overall slightly modified code to the earlier example using the approach above will look like the following:

import java.awt.*;
import objectdraw.*;

public class HelloWorld extends WindowController
{

	public void onMouseMove(Location point)
	{
		Text myText;
		
		canvas.clear();
		myText = new Text("Hello world!", point, canvas);
		myText.setFontSize(30);
		myText.setColor(Color.red);
	}
	
	
	public static void main(String[] args) 
	{
		new HelloWorld().startController(400, 400);
	}

}

 

BYeHKvj.png

 

 

Instead of creating and clearing it every time, let's just move the one Text object itself by rearranging the code around a little bit.  We'll create the Text object by clicking, check if the object exists with a conditional if() statement, and use moveTo() wherever the cursor is.  Every time you click you'll create a new one; so it'll act like a stamp!

 

import java.awt.*;
import objectdraw.*;

public class HelloWorld extends WindowController
{
	
	// declared like a global variable
	Text myText;
	
	public void onMouseMove(Location point)
	{
		/* Check if the object exists
		 * Code can run without checking, but will show errors in the console */
		if(myText != null)
		{
			// Move myText to wherever my point is
			myText.moveTo(point);			
		}		
	}
	
	public void onMouseClick(Location point)
	{
		// We'll create the text upon clicking
		myText = new Text("Hello world!", point, canvas);
		myText.setFontSize(30);
		myText.setColor(Color.red);
	}
	
	
	public static void main(String[] args) 
	{
		new HelloWorld().startController(400, 400);
		
	}

}

 

Want to try it with other objects?  Let's do it with a circle instead.  We'll create a circle (FilledOval that i'll call myCircle) and we'll make it fall to the bottom of the window controller.  Create the circle with:

 

myCircle = new FilledOval(point, ovalWidth, ovalHeight, canvas);

 

We can create another java project to handle active objects, which is what I'll do for this tutorial; you can also create a new class in the same project and skip adding the classpath later (less reusable).  To follow this tutorial: Create a new project just like we did HelloWorld and we'll call it something like FallingObject.  Setup the build configuration with Objectdraw and add a new class just as above.  The code will look suspiciously similar to what you can find in a textbook, but the setup in Eclipse can be frustrating and will be added here.  I promise to expand on this more so that you can adapt the code to your project goals.

 

import objectdraw.*;
import java.awt.*;

public class FallingObject extends ActiveObject
{
	
	private DrawingCanvas canvas;
	private FilledOval myCircle;
	private double fallingRate=5;
	
	public FallingObject(Location point, DrawingCanvas aCanvas)
	{
		double ovalWidth=50, ovalHeight=50;
		
		canvas = aCanvas;
		
		// Create the object here
		myCircle = new FilledOval(point, ovalWidth, ovalHeight, canvas);
		
		// Starts when extends WindowController (notice above it's ActiveObject this time)
		start();
	}
	
	public void run()
	{
		// getY is the Y-location of myCircle and we want it to keep going until it's off the canvas
		while(myCircle.getY()<canvas.getHeight())
		{
			// fallingRate is the distance it'll move along the Y-axis (up or down)
			myCircle.move(0, fallingRate);
			
			// Absolutely necessary to have a small delay before looping (try it without)
			pause(30);
		}
		
		// Once it's off the y-axis lets remove it from the canvas
		myCircle.removeFromCanvas();
	}

}

 

You can reuse HelloWorld or create a new project.  I've opted to create a new project called Test.  Same as before, but we'll need to do something else (during the build configuration): Add the classpath you just wrote to your project (unless you decided to create this class in the same project).

 

Puconh8.png

 

Whichever project you use to run the code (Test or HelloWorld): Use this code.  You'll call for your new ActiveObject (we called FallingObject) and create a WindowController to use.

 

import objectdraw.*;
import java.awt.*;

public class Test extends WindowController
{
	FilledOval myCircle;
	
	public void onMouseClick(Location point)
	{
		// Use our active object
		new FallingObject(point, canvas);
	}
	
	// We need the window controller still
	public static void main(String[] args)
	{
		new Test().startController(500, 500);
	}
}

 

Run as a Java application and click on the screen.  The circles will fall wherever you click.

 

QfqPjH0.png

 

Not enough to make that game you've always wanted to make?  Let's add our own images with getImage().  A modest adjustment to the code in FallingObject by removing the FilledOval.  Again: Suspiciously similar to the textbooks.

 

import objectdraw.*;
import java.awt.*;

public class FallingObject extends ActiveObject
{
	
	private DrawingCanvas canvas;
	private VisibleImage myGraphic;
	private double fallingRate=3;
	
  	// It's important to recognize here, that I've added Image myImage as a paramater here, which will be passing to here from the other class.
	public FallingObject(Image myImage, Location point, DrawingCanvas aCanvas)
	{
		
		canvas = aCanvas;
		
		/* Use the image we just got from the parameters above (inside parentheses of FallingObject(...))
		 * We'll create the image in begin() on the other file */
		myGraphic = new VisibleImage(myImage, point, canvas);
		
		// Starts when extends WindowController (notice above it's ActiveObject this time)
		start();
	}
	
	public void run()
	{
		// getY is the Y-location of myGraphic and we want it to keep going until it's off the canvas
		while(myGraphic.getY()<canvas.getHeight())
		{
			// fallingRate is the distance it'll move along the Y-axis (up or down)
			myGraphic.move(0, fallingRate);
			
			// Absolutely necessary to have a small delay before looping (try it without)
			pause(30);
		}
		
		// Once it's off the y-axis lets remove it from the canvas
		myGraphic.removeFromCanvas();
	}

}

 

Back to the other file that extends the WindowController (I did it in a new project called Text although you may have continued with HelloWorld- stay consistent).  Right click on src (source) and import the image you want to use.  I'm going to use "Joshy.png" from my desktop.

 

7BlDMET.png

 

 

Then another modest change to the code to get the image and run the ActiveObject.

import objectdraw.*;
import java.awt.*;

public class Test extends WindowController
{
	Image myImage;
	
	// We'll need to initialize by getting the image
	public void begin()
	{
		myImage = getImage("Joshy.png");
	}
	
	public void onMouseClick(Location point)
	{
		
		// Notice that myImage is now in here too; it's being passed to FallingObject
		new FallingObject(myImage, point, canvas);
	}
	
	// We need the window controller still
	public static void main(String[] args)
	{
		new Test().startController(500, 500);
	}
}

 

Run the Java application.

 

XQr6hFb.png

 

It can be seen in action (Of course!  I had to find another way to share a picture of my wife and I).

 

 

Next steps. 

 

This time: It's up to you.  No doubt I will revisit this in the future (hopefully with templates or examples), but for now you can use more images; respond to more events, and enjoy. 

 

  • Many classroom examples would have you build a games like Pong using filledRect and filledOval; set the sides and top as a wall (use conditional statements from the other guides if getX is greater than or less than, then change the ball direction using move), and have the filledRect follow your cursor onMouseMove or onMouseDrag.  Here's the code for a single player -like version with just the player bar to help  you get started; it needs the ball using similar logic and a good way to test it is to make a class with only the ball bouncing off the walls of the canvas.

 

import java.awt.*;
import objectdraw.*;

public class Pong extends WindowController 
{
	
	FilledRect playerBar;
	double barWidth=100, barHeight=20;
	
	public void begin()
	{
		// place the player bar at the bottom
		playerBar = new FilledRect(0.5*canvas.getWidth()-0.5*barWidth, canvas.getHeight()-barHeight, barWidth, barHeight, canvas);
	}
	
	public void onMouseMove(Location point)
	{
		double leftWall, rightWall, positionX, positionY=canvas.getHeight()-barHeight;
		
		// Setting boundary conditions to prevent bar from going past the wall
		leftWall=0.5*barWidth;
		rightWall=canvas.getWidth()-0.5*barWidth;
		
		if(playerBar != null)
		{
			// Use if statement to fix points if outside the controller
			if(point.getX()<leftWall)
			{
				// We've hit the left wall so fix the value
				positionX=0;
			}
			else if(point.getX()>rightWall)
			{
				// We've hit the right wall so fix the value
				positionX=canvas.getWidth()-barWidth;
			}
			else
			{
				// Default
				positionX=point.getX()-0.5*barWidth;
			}
			
			// Move the bar	
			playerBar.moveTo(positionX, positionY);			
		}	
	}

	public static void main(String[] args) 
	{
		new Pong().startController(700, 500);
	}

}

 

 

More about conditional statements can be found in the other guide, and the good news is it works the same.  if(condition){ //action}.

 

Here's some example code to get the ball to bounce off the wall, and so the reader is encouraged to try mixing the two with some modifications for the complete game.

 

import objectdraw.*;
import java.awt.*;

public class BallMove extends ActiveObject
{
	
	private DrawingCanvas canvas;
	private FilledOval myBall;
	private double velocityX, velocityY;
	
	public BallMove(FilledOval myOval, Location point, double directionX, double directionY, DrawingCanvas aCanvas)
	{
		
		canvas = aCanvas;
		myBall = myOval;
		velocityX=directionX;
		velocityY=directionY;
		start();
	}
	
	public void run()
	{	
		
		// Will define values inside while loop in case canvas dimensions change
		double leftWall, rightWall, topWall, bottomWall, speedScalar=5;
		
		while(true)
		{
			
          		// If you place this outside the while loop and change the canvas, then the boundary conditions wont adjust- try it!
			leftWall=0; 
			rightWall=canvas.getWidth()-myBall.getWidth(); 
			topWall=0; 
			bottomWall=canvas.getHeight()-myBall.getHeight();
			
			// Check for walls
			if(myBall.getX()<=leftWall || myBall.getX()>=rightWall)
			{
				velocityX*=-1;

			}
			if(myBall.getY()<=topWall || myBall.getY()>=bottomWall)
			{
				velocityY*=-1;
			}
			
			// What happens if speedScalar is too high, and when is it too high?
			myBall.move(speedScalar*velocityX, speedScalar*velocityY);
			pause(30);	
		}		
	}
}

 

  • Add a new Text that shows how many balls are in the canvas.
  • Change the colour or the size of the ball when it hits a wall using

 

// choose a colour
myBall.setColor(Color.red);
  
// choose a size
myBall.setSize(10, 10);

 

  • You could use move and moveTo in a way where you have an image at the center of the canvas ie. a character and move the background image in response to where you click (maybe hover around space or have a character walk around some land area).  Here's an example I made with a spaceship only modifying the code a little bit.  Careful bookkeeping of the map called myGraphic is the key thing here so that I can move that object between the two classes (instead of creating a new one like the ball examples above).

 

From FallingObject

import objectdraw.*;
import java.awt.*;

public class FallingObject extends ActiveObject
{
	
	private DrawingCanvas canvas;
	private double clickX, clickY;
	private VisibleImage myGraphic;
	
	public FallingObject(VisibleImage myImage, Location point, DrawingCanvas aCanvas)
	{
		
		canvas = aCanvas;
		
		myGraphic = myImage;
      
      		// Bookkeeping where I clicked at
		clickX=point.getX();
		clickY=point.getY();
		
		start();
	}
	
	public void run()
	{		
      
      			// I added steps to break up the movement into small "step" slices.  More steps and smaller delay looks more smooth just like the television
			double steps=100;
		
			for(int i=0; i<steps; i++)
			{
              
              			// A little bit of math to get a "vector" from the center of the Window controller to the point I clicked
				myGraphic.move((0.5*canvas.getWidth()-clickX)/steps, (0.5*canvas.getHeight()-clickY)/steps);
			
				// Absolutely necessary to have a small delay before looping (try it without)
				pause(30);			
			}
	}

}

 

and Test

import objectdraw.*;
import java.awt.*;

public class Test extends WindowController
{
	Image backgroundImage, myShip;
	VisibleImage myGraphic;
	
	// We'll need to initialize by getting the image
	public void begin()
	{		
		// Get the image during start
		backgroundImage = getImage("stars.png");
		myShip = getImage("ship.png");
		
		myGraphic = new VisibleImage(backgroundImage, 0, 0, canvas);
		
		// place my ship at the center of canvas
		new VisibleImage(myShip, 0.5*canvas.getWidth(), 0.5*canvas.getHeight(), canvas);
		
	}
	
	public void onMouseClick(Location point)
	{
      
      		// I'm sending the map to be moved (not the ship)
		new FallingObject(myGraphic, point, canvas);
	}
	
	// We need the window controller still
	public static void main(String[] args)
	{
		new Test().startController(1000, 600);
	}
}

 

The results

 

  • Setup an array with ones in random locations; if you click on a location, then something happens (you win or you lose depending on the game ie. battleship or minesweeper).
  • Use a function to determine how your objects move.  Here's a formula that will make things spiral from an inner radius to an outer radius (I imagine this would be tempting for any Dragon Ball Z fan; however: We'll stick to a modern hello world).  Multiply the radius with sinusoidals (sin() and cos()) while sweeping t in a loop.

 

double radiusScale(double innerRadius, double outerRadius, double t, double finalValue)
	{
		double finalRadius;
		double alpha;
		
		alpha=t/finalValue;
		
		finalRadius=(1-alpha)*innerRadius+alpha*outerRadius;
		
		return finalRadius;
	}

 

 

  • Like giving your characters an item?  Use a function to see if you grabbed the item or if the object is within an area; if you drop it on top of your character, then update the photo such that it's the character with the item!  You can also fix the position of the object to follow the other object too.
  • Remove the object.contains(Location point code) in the code below and try using the function with different boundary or conditional statements.
  • Edit the wall bounce code above using other object.contains or the grabItem function below by having the balls bounce when they hit each other (hint: Strategy is to assign new FilledOval to a FilledOval object array ie. myBall[1] and myBall[2]... and perform a check every time the ball moves; you can also be more efficient by using getLocation and store the distance into an array, and you know you wont have to do a check until your iteration/velocity is at least the smallest value in that array).
import objectdraw.*;
import java.awt.*;

public class CombineItems extends WindowController
{
	private Image myCharacter, anItem, combinedItems;
	private VisibleImage myGraphic, itemGraphic;
	private int dragCounter=0;
	private double oldHeight, newHeight;
	
	// We'll need to initialize by getting the image
	public void begin()
	{		
		// retrieve three graphics not on display
		myCharacter = getImage("Joshy.png");
		anItem = getImage("Crown.png");
		combinedItems = getImage("CombinedPhoto.png");
		
		// two of the graphics are visible for now at separate location
		myGraphic = new VisibleImage(myCharacter, 100, 150, canvas);
		itemGraphic = new VisibleImage(anItem, 600, 300, canvas);
		
		oldHeight=myGraphic.getHeight();
		
	}
	
	public void onMouseDrag(Location point)
	{

		// If item is selected on the first click (dragCounter), then you can move it!
		// if(grabItem(itemGraphic, point) && dragCounter==0) using function equivalent below
		if(itemGraphic.contains(point) && dragCounter==0)
		{
			itemGraphic.moveTo(point.getX()-0.5*itemGraphic.getWidth(), point.getY()-0.5*itemGraphic.getHeight());
		}
		else
		{
			// Increase so that people cannot just drag their cursor across to select it
			dragCounter++;
		}	
		
	}
	
	public void onMouseRelease(Location point)
	{
		// reset dragCounter so that we can click again
		dragCounter=0;
		
		// see if it the item landed on top of the character, if it did then let's combine them!
		// if(grabItem(myGraphic, point)) // using function equivalent below
		if(myGraphic.contains(point))
		{
			// combine the items (new image)
			myGraphic.setImage(combinedItems);
			newHeight = myGraphic.getHeight();
			
			// delete the item
			itemGraphic.removeFromCanvas();
			
			// The height of the new image will need to be accounted for
			myGraphic.move(0, oldHeight-newHeight);
		}
	}
	
	// We need the window controller still
	public static void main(String[] args)
	{
		new CombineItems().startController(1000, 600);
	}
	
	/* Function equivalent of object.contains(Location point) can use for special shapes
	 * This function is not required for functionality */
	public static Boolean grabItem(VisibleImage selectedObject, Location point)
	{
		double imageWidth=selectedObject.getWidth(),
			   imageHeight=selectedObject.getHeight(),
			   imageX=selectedObject.getX(),
			   imageY=selectedObject.getY();
		Boolean test=false;
		
		/* Use inequalities to check boundary conditions in a bounded box
		 * can change boundary conditions to other shapes like a circle */
		if( (point.getX()>=imageX) && (point.getX()<=(imageX+imageWidth)) 
				&& (point.getY()<=(imageY+imageHeight)) && (point.getY()>=imageY) )
		{
		
			test=true;
		}
		
		return test;
	}
	
}

 

Edited by Joshy

PoorWDm.png?width=360&height=152

Share this post


Link to post
Share on other sites


You know, I haven't ever seriously tried developing a GUI program with java. I just found SFML with C++ to be a much more enjoyable experience. But at the same time, I tried making a GUI program with java when I only had like 2 months of programming experience. I should probably go back and try it again when I get the chance. Hell I might even use this tutorial to get myself started with it haha. Thanks for the tutorial Joshy, hope your day is going well miboi


I write programs and stuff.

 

If you need to contact me, here is my discord tag: Dustin#6688

 

I am a busy person. So responses may be delayed.

1840045955_Thicco(1).thumb.png.87c04f05633286f3b45b381b4acc4602.png

 

Share this post


Link to post
Share on other sites


  • 2 weeks later...

I don't usually bump the posts, but I've made a few edits and updates.  If this is your first time programming, then I strongly suggest going through the previous guides in the series I had posted.  I've been asked questions about some of the content in here at interviews and the answers/approaches are well-received.


PoorWDm.png?width=360&height=152

Share this post


Link to post
Share on other sites


Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


×
×
  • Create New...