I have a project that on it's own functions as I would like it to. It's a small game about the player (a blob) picking up randomly spawning items in an attempt to keep their "happiness" from hitting 0.
I originally wrote it in BlueJ, but I asked a friend who is more adept in programming about giving it graphics. He said that while the swing package would work, it would be better in Eclipse with Processing.
I set it up with him on my computer over Skype, moved all my files from BlueJ to Eclipse, and began working on making a class for the visuals to function it.
Here's the code (All variables and functions from the Map class are functioning):
public void setup()
{
//int x = gameMap.getXScale()*5 + 5*(xSC+2);
//int y = gameMap.getYScale()*5 + 5*(ySC+2) + 150;
gameMap = new Map(MapTypes.treasureRoom(), BlobTypes.trBlob());
xSC = gameMap.getXScale();
ySC = gameMap.getYScale();
sze = 100;
spc = 5;
int x = gameMap.getXScale()*5 + 5*(xSC+2);
int y = gameMap.getYScale()*5 + 5*(ySC+2) + 150;
size(x,y);
}
public void draw()
{
int[] rgb = gameMap.getBlob().getRGBVal();
int r = 204;
int g = 102;
int b = 0;
Node[][] n = gameMap.getMapOfNodes();
background(0);
for(int i = 0; i < ySC; i ++){
for(int j = 0; j < xSC; j++){
if(n[j][i].getNodeType() == 0){
r = 128;
g = 128;
b = 128;
}else if(n[j][i].getNodeType() == 1){
r = rgb[0];
g = rgb[1];
b = rgb[2];
}else if(n[j][i].getNodeType() == 2){
r = 204;
g = 153;
b = 255;
}else if(n[j][i].getNodeType() == 3){
r = 0;
g = 0;
b = 0;
}
rectt(j*10+spc, i*10+spc, sze, sze, 5, r, g, b);
}
}
fill(100);
rect(50, 50, 100, 100);
}
void rectt(float x, float y, float w, float h, float ra, int r, int b, int g)
{
fill(r,b,g);
rect(x, y, w, h, ra);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
It is inside a Game() class that extends PApplet. When I try running it (as an application), no screen shows up at all. What do I do?
EDIT: The Node[][] near the beginning of draw() is an array of each individual point on the Map that the player can be. Also, the MapTypes and BlobTypes objects are just a collection of methods for storing different Map objects and Blob (the player) objects.
you aren't calling anything in your main method class
public static void main(String[] args) {
// TODO Auto-generated method stub
}
I can't personally tell you what all you need to call from this class but it should be something like this
public static void main(String[] args) {
ThisClass main = new ThisClass(parameters if any);
main.setup();
while(game is not over){
main.draw();
update other game logic
}
}
As a note, one iteration of your while loop is equvilant to one frame. So everything you want to be accomplished per frame, must be placed in here.
Related
I'm writing a program which updates a canvas after every key press by regenerating a data structure (cube) and then painting this onto the canvas. If the user enters 'S' I want the canvas to display the cube after every turn (turn = one character of the solution string generated by the program) every 100ms and redraw this to the screen, have tried several different approaches but can't get it to work. This is my KeyListener code:
canvas.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
GC gc = new GC(canvas);
Rectangle rect = canvas.getClientArea();
String alg = ""+e.character;
cube.performAlgorithm(alg, false);
drawCube(rect,gc);
if(e.character=='S'){
Cube cube2 = new Cube(cube);
String solution = Solutions.longsolve(cube2, "Fridrich", false);
String[] moves = new String[solution.length()];
moves = solution.split("(?!^)");
for(String move : moves){
cube.performAlgorithm(move, false);
try {
drawCube(rect,gc);
canvas.redraw();
canvas.update();
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
//System.out.println(solution);
}
gc.dispose();
}
});
and my drawFace and drawCube code, appreciate this may not be a very nice way of solving my problem but I'm very new to using SWT.
private static void drawFace(GC gc, int startwidth, int startdepth, int celldim, Color[] colour, byte[][] Face){
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
int x = startwidth;
int y = startdepth;
//draw face of the cube
for(int i = 0; i<3; i++){
for(int j = 0; j<3; j++){
Rectangle rect = new Rectangle(x, y, celldim, celldim);
gc.setBackground(colour[Face[i][j]]);
gc.fillRectangle(rect);
gc.drawRectangle(rect);
x += celldim;
//only draw a box
}
x = startwidth;
y+=celldim;
}
}
private static void drawCube(Rectangle clientArea, GC gc){
int startdepth = 10;
int celldim = (((clientArea.height)-(startdepth*2))/12);
int startwidth = (int) ((int)(clientArea.width/2)-(1.5*celldim));
Color[] colours = {gc.getDevice().getSystemColor(SWT.COLOR_GREEN),gc.getDevice().getSystemColor(SWT.COLOR_RED),
gc.getDevice().getSystemColor(SWT.COLOR_BLUE),gc.getDevice().getSystemColor(SWT.COLOR_GRAY),
gc.getDevice().getSystemColor(SWT.COLOR_BLACK),gc.getDevice().getSystemColor(SWT.COLOR_YELLOW)};
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
int x = startwidth;
int y = startdepth;
drawFace(gc, x, y, celldim,colours,cube.Uface);
y += (3*celldim);
drawFace(gc, x, y, celldim,colours,cube.Fface);
x -= (3*celldim);
drawFace(gc, x, y, celldim,colours,cube.Lface);
x += (6*celldim);
drawFace(gc, x, y, celldim,colours,cube.Rface);
x -= (3*celldim);
y += (3*celldim);
drawFace(gc, x, y, celldim,colours,cube.Dface);
y += (3*celldim);
drawFace(gc, x, y, celldim,colours,cube.Bface);
}
You can't do updates in a loop like that because you must let the main SWT Display.readAndDispatch loop run since this is what actually updates the screen.
Instead use Display.timerExec to execute one step of the loop every 100ms:
Display.getDefault().timerExec(100, new Runnable() {
#Override
public void run() {
canvas.redraw();
// Run again - TODO add logic to stop after correct number of moves
Display.getDefault().timerExec(100, this);
}
});
You should just call redraw in this routine, all the actual drawing should be in a paint listener on the control.
Relatively new to Java, coding for a school project.
I'm using JFrame and JComponent, drawing patterns and strings and all that fun stuff.
Currently, I have a class written that extends JComponent. This is the class where I am defining most of my shapes. The issue is that I initialized my Jframe
(Code: JFrame myFrame = new JFrame() ) in the main of one class, but I need to access myFrame.getWidth() in the JComponent class that I'm working in.
How can I access variables getWidth() and getHeight() in "public class MyJComponent extends JComponent" , when I defined myFrame in 'public class Lab2' ??
Edit for code:
public class Lab2 {
public static void main(String[] args) {
System.out.println("Hello Java");
JFrame myFrame = new JFrame();
myFrame.setSize(500, 500);
myFrame.setTitle("Color Test");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyJComponent myComponent = new MyJComponent(500, 500);
myFrame.add(myComponent);
myFrame.getContentPane().setBackground(Color.white); //sets background color.
myFrame.setVisible(true); // setVisible() *after* add() is the norm
//Deciding geometry of hidden shape. paintComponent is called once per run, this is called afterwards.
}
}
/**/
public class MyJComponent extends JComponent {
int[] circleX;
int[] circleY;
int[] circleR;
final int MIN_RADIUS = 5;
final int MAX_RADIUS = 15;
final int MIN_SEPARATION = 1;
final int MAX_ATTEMPTS = 5000;
final int MAX_CIRCLES = 1000;
Random rand;
int initialWidth;
int initialHeight;
int numCircles; // actual number of circles drawn
// are circles at index i and index j separated by *<= tolerance* pixels?
boolean twoCirclesOverlap(int i, int j, int tolerance) {
double distanceBetweenCenters =
Math.sqrt((circleX[i] - circleX[j]) * (circleX[i] - circleX[j]) +
(circleY[i] - circleY[j]) * (circleY[i] - circleY[j]));
return (distanceBetweenCenters <= (circleR[i] + circleR[j] + tolerance));
}
// are any existing circles separated from the proposed one at index i by *<= tolerance* pixels?
boolean anyCirclesOverlap(int i, int tolerance) {
for (int j = 0; j < i; j++) {
if (twoCirclesOverlap(i, j, tolerance)) {
return true;
}
}
return false;
}
// attempt to randomly place the largest-possible circle that does not overlap any existing one
boolean tryToPlaceCircle(int i) {
for (int j = 0; j < MAX_ATTEMPTS; j++) {
// pick a random position, set initial radius to minimum
circleX[i] = rand.nextInt(initialWidth);
circleY[i] = rand.nextInt(initialHeight);
circleR[i] = MIN_RADIUS;
// grow circle until it touches another or reaches max size
while (!anyCirclesOverlap(i, MIN_SEPARATION) && circleR[i] < MAX_RADIUS)
circleR[i]++;
// it was touching from the start -- must try again
if (circleR[i] == MIN_RADIUS) {
continue;
}
// grew to max size -- well done
else if (circleR[i] == MAX_RADIUS) {
return true;
}
// grew some, but then touched
else {
circleR[i]--; // retract to the step before touch
return true;
}
}
// all attempts failed
return false;
}
MyJComponent(int width, int height) {
circleX = new int[MAX_CIRCLES];
circleY = new int[MAX_CIRCLES];
circleR = new int[MAX_CIRCLES];
initialWidth = width;
initialHeight = height;
rand = new Random();
numCircles = 0;
while (numCircles < MAX_CIRCLES && tryToPlaceCircle(numCircles)) {
numCircles++;
}
}
//Override paintComponent
public void paintComponent(Graphics g) {
for (int i = 0; i < numCircles; i++) {
g.drawOval(circleX[i] - circleR[i], circleY[i] - circleR[i], 2 * circleR[i], 2 * circleR[i]);
}
}
//Shape decision
public void shapeDecision() {
double randomShapeDecider = Math.random();
if (randomShapeDecider > .50) {
//shape is circle, define it's properties
hiddenCircleDiameter = myFrame.getWidth();
}
else {
//shape is rectangle
hiddenRectangleWidth = myFrame.getWidth();
}
}
}
So, I have been working on this program for drawing a star from a circle created using g.fillPolygon(int, int, int). I was intially having issues with creating an entire circle, but changed double angle = (i * 360) to (i * 720) to fix that (may be a band-aid fix, not sure yet). Now I'm in the process of attempting to connect all the points together (as shown in the "Target Output" section).
Note: I believe that the labeling of the points shown in the modification section was not done wih Java.
My Code: (Where I'm at right now)
import java.awt.*;
public class StarSampler {
public static void main(String[] args)
{
DrawingPanel panel = new DrawingPanel(500, 500);
Graphics2D g = panel.getGraphics();
g.setColor(Color.YELLOW);
fillStar(g, 250, 250, 150, 50, .7);
}
public static void fillStar(Graphics2D g, int ctrX, int ctrY, int radius, int nPoints, double spikiness)
{
double xDouble[] = new double[2*nPoints];
double yDouble[] = new double[2*nPoints];
int xPoint[] = new int[100];
int yPoint[] = new int[100];
for (int i = 0; i < 2*nPoints; i++)
{
double iRadius = (i % 2 == 0) ? radius : (radius * spikiness);
double angle = (i * 720.0) / (2*nPoints);
xDouble[i] = ctrX + iRadius * Math.cos(Math.toRadians(angle));
yDouble[i] = ctrY + iRadius * Math.sin(Math.toRadians(angle));
for (int j = 0; j < nPoints; j++) // Casts for ints and doubles
{
xPoint[j] = (int) xDouble[j];
yPoint[j] = (int) yDouble[j];
}
}
g.fillPolygon(xPoint, yPoint, nPoints); // Creates polygon but
}
}
My Code's Output:
Target Output (What I'm generally aiming for, not both together):
I am trying to implement a plot of a Julia Set using a Canvas inside a JFrame. For some reason it seems that setColor() does not work. Here's the responsible code:
#Override
public void paint(Graphics aGraphics)
{
// store on screen graphics
Graphics cScreenGraphics = aGraphics;
// render on background image
aGraphics = m_cBackGroundImage.getGraphics();
for(int i = 0; i < m_iWidth; i++)
{
for(int j = 0; j < m_iHeight; j++)
{
int r = m_iPixelRed[i][j];
int g = m_iPixelGreen[i][j];
int b = m_iPixelBlue[i][j];
aGraphics.setColor(new Color(r, g, b));
aGraphics.drawRect(i, j, 0, 0);
}
}
// rendering is done, draw background image to on screen graphics
cScreenGraphics.drawImage(m_cBackGroundImage, 1, 1, null);
}
At first I suspected that the values were not passed to m_iPixel... correctly, so I hardcoded the values to 0xff in the calling function. I checked this via r, g, b and am certain that they are all set to that value, yet the canvas is black.
The funny thing is: when I enter aGraphics.setColor(Color.WHITE) or aGraphics.setColor(0xff, 0xff, 0xff) instead of the variables r, g, b it works! Even though I checked the variables to be at the same value and hard coded them earlier to 0xff. I am completely out of ideas as to what could be the issue...
EDIT:
The values were hardcoded as follows:
public void setPixelColour(int i, int j, int r, int g, int b)
{
m_iPixelRed[i][j] = 0xff;
m_iPixelGreen[i][j] = 0xff;
m_iPixelBlue[i][j] = 0xff;
}
setPixelColour was called by the superclass in this method:
private void calcColour(int i, int j, int aIterations)
{
m_cCanvas.setPixelColour(i, j, 0XFF, 0xff, 0XFF);
}
Which was in turn called by this loop.
for(int i = 0; i < iCanvasHeight; i++){
for(int j = 0; j < iCanvasWidth; j++){
cSum.setRe(m_cCoordPlane[i][j].getRe());
cSum.setIm(m_cCoordPlane[i][j].getIm());
m_iIterations[i][j] = 0;
do{
m_iIterations[i][j]++;
cSum = cSum.square();
cSum = cSum.add(m_cSummand);
m_dAbsSqValues[i][j] = cSum.getAbsSq();
}while((m_iIterations[i][j] < MAXITER) && (m_dAbsSqValues[i][j] < m_iDivergThresh));
this.calcColour(i, j, m_iIterations[i][j]);
m_cMsgIter = "x = " + i + " , y = " + j;
this.repaint();
}
}
I checked made sure that this loop is definitely completed. I checked the values again using the debugger right before setColor(). Since I don't trust the debugger (out of experience) I checked another time with the console by adding System.out.println("r = " + Integer.toString(r) + " g = " + Integer.toString(g) + " b = " + Integer.toString(b)); right before setColor().
EDIT:
This is my paint method of the JFrame:
public void paint(Graphics aGraphics)
{
Graphics cScreenGraphics = aGraphics;
// render on background image
aGraphics = m_cBackGroundImage.getGraphics();
this.paintComponents(aGraphics);
// drawString() calls are debug code only...
aGraphics.setColor(Color.BLACK);
aGraphics.drawString(m_cSMsg, 10, 450);
aGraphics.drawString(m_cMsgIter, 10, 465);
aGraphics.drawString(m_cMsgDivThresh, 10, 480);
// rendering is done, draw background image to on screen graphics
cScreenGraphics.drawImage(m_cBackGroundImage, 0, 0, null);
}
Not sure if posting big chunks of code in comments makes a whole lot of sense so here's my test code for you:
package test;
import javax.swing.JFrame;
public class Test
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
MyCanvas canvas = new MyCanvas();
frame.add(canvas);
frame.pack();
frame.setVisible(true);
for(int i = 0; i < 800; i++)
{
for(int j = 0; j < 600; j++)
{
canvas.setPixelColour(i, j, 0XFF, 0xff, 0XFF);
canvas.repaint();
}
}
}
}
And this is the MyCanvas class:
package test;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
public class MyCanvas extends java.awt.Canvas
{
private BufferedImage m_cBackGroundImage;
private int[][] m_iPixelRed, m_iPixelGreen, m_iPixelBlue;
private int m_iWidth, m_iHeight;
public MyCanvas()
{
setPreferredSize(new Dimension(800, 600));
m_iWidth = 800;
m_iHeight = 600;
m_cBackGroundImage = new BufferedImage(m_iWidth, m_iHeight, BufferedImage.TYPE_INT_ARGB);
m_iPixelRed = new int[m_iWidth][m_iHeight];
m_iPixelGreen = new int[m_iWidth][m_iHeight];
m_iPixelBlue = new int[m_iWidth][m_iHeight];
}
public void paint(Graphics aGraphics)
{
Graphics cScreenGraphics = aGraphics;
aGraphics = m_cBackGroundImage.getGraphics();
for(int i = 0; i < m_iWidth; i++)
{
for(int j = 0; j < m_iHeight; j++)
{
int r = m_iPixelRed[i][j];
int g = m_iPixelGreen[i][j];
int b = m_iPixelBlue[i][j];
aGraphics.setColor(new Color(r, g, b));
aGraphics.drawRect(i, j, 0, 0);
}
}
cScreenGraphics.drawImage(m_cBackGroundImage, 1, 1, null);
}
public void setPixelColour(int i, int j, int r, int g, int b)
{
m_iPixelRed[i][j] = r;
m_iPixelGreen[i][j] = g;
m_iPixelBlue[i][j] = b;
}
}
I tried staying as close to what you provided as possible (even though your naming convention is not really my kind of thing). The main changes were in the loop in the main method because I didn't need most of that code. I also obliterated the calcColor method because it simply called a different method.
Anyway, this works for me (= I get a white canvas). I also tried changing the 0xff s to (int)(Math.random() * 255) which will result in a... let's go with rainbow-colored canvas, so it seems to be working fine.
I'm trying to run this code:
import TUIO.*;
TuioProcessing tuioClient;
// Grid
int cols = 6, rows = 6;
boolean[][] states = new boolean[cols][rows];
int videoScale = 100;
// these are some helper variables which are used
// to create scalable graphical feedback
float cursor_size = 15;
float object_size = 60;
float table_size = 760;
float scale_factor = 1;
PFont font;
boolean verbose = false; // print console debug messages
boolean callback = true; // updates only after callbacks
void setup(){
size(600,600);
noCursor();
noStroke();
fill(0);
// periodic updates
if (!callback) {
frameRate(60); //<>//
loop();
} else noLoop(); // or callback updates
font = createFont("Arial", 18);
scale_factor = height/table_size;
// finally we create an instance of the TuioProcessing client
// since we add "this" class as an argument the TuioProcessing class expects
// an implementation of the TUIO callback methods in this class (see below)
tuioClient = new TuioProcessing(this);
}
void draw()
{
// Begin loop for columns
for (int i = 0; i < cols; i++) {
// Begin loop for rows
for (int j = 0; j < rows; j++) {
// Scaling up to draw a rectangle at (x,y)
int x = i*videoScale;
int y = j*videoScale;
fill(255);
stroke(0);
//check if coordinates are within a box (these are mouse x,y but could be fiducial x,y)
//simply look for bounds (left,right,top,bottom)
rect(x,y,videoScale,videoScale);
}
}
textFont(font,18*scale_factor);
float obj_size = object_size*scale_factor;
float cur_size = cursor_size*scale_factor;
ArrayList<TuioObject> tuioObjectList = tuioClient.getTuioObjectList();
for (int i=0;i<tuioObjectList.size();i++) {
TuioObject tobj = tuioObjectList.get(i);
stroke(0);
fill(0,0,0);
pushMatrix();
translate(tobj.getScreenX(width),tobj.getScreenY(height));
rotate(tobj.getAngle());
rect(-obj_size/2,-obj_size/2,obj_size,obj_size);
popMatrix();
fill(255);
text(""+tobj.getSymbolID(), tobj.getScreenX(width), tobj.getScreenY(height));
}
ArrayList<TuioCursor> tuioCursorList = tuioClient.getTuioCursorList();
for (int i=0;i<tuioCursorList.size();i++) {
TuioCursor tcur = tuioCursorList.get(i);
ArrayList<TuioPoint> pointList = tcur.getPath();
if (pointList.size()>0) {
stroke(0,0,255);
TuioPoint start_point = pointList.get(0);
for (int j=0;j<pointList.size();j++) {
TuioPoint end_point = pointList.get(j);
line(start_point.getScreenX(width),start_point.getScreenY(height),end_point.getScreenX(width),end_point.getScreenY(height));
start_point = end_point;
}
stroke(192,192,192);
fill(192,192,192);
ellipse( tcur.getScreenX(width), tcur.getScreenY(height),cur_size,cur_size);
fill(0);
text(""+ tcur.getCursorID(), tcur.getScreenX(width)-5, tcur.getScreenY(height)+5);
}
}
ArrayList<TuioBlob> tuioBlobList = tuioClient.getTuioBlobList();
for (int i=0;i<tuioBlobList.size();i++) {
TuioBlob tblb = tuioBlobList.get(i);
stroke(0);
fill(0);
pushMatrix();
translate(tblb.getScreenX(width),tblb.getScreenY(height));
rotate(tblb.getAngle());
ellipse(-1*tblb.getScreenWidth(width)/2,-1*tblb.getScreenHeight(height)/2, tblb.getScreenWidth(width), tblb.getScreenWidth(width));
popMatrix();
fill(255);
text(""+tblb.getBlobID(), tblb.getScreenX(width), tblb.getScreenX(width));
}
}
// --------------------------------------------------------------
// these callback methods are called whenever a TUIO event occurs
// there are three callbacks for add/set/del events for each object/cursor/blob type
// the final refresh callback marks the end of each TUIO frame
// called when an object is added to the scene
void addTuioObject(TuioObject tobj) {
if (verbose) println("add obj "+tobj.getSymbolID()+" ("+tobj.getSessionID()+") "+tobj.getX()+" "+tobj.getY()+" "+tobj.getAngle());
double fx = tobj.getX();
double fy = tobj.getY();
println (fx + " " + fy);
if( (fx >= x && fx <= x + videoScale) && //check horzontal
(fy >= y && fy <= y + videoScale)){
//coordinates are within a box, do something about it
fill(0);
stroke(255);
//you can keep track of the boxes states (contains x,y or not)
states[i][j] = true;
}
}
But I get the error "The field component.x is not visible" regarding the last if statement. I tried to make x and y public when I declared them in the draw method but I get the error "illegal modifier for the variable x; only final is permitted".
How could I fix this ?
Thanks for taking the time to read and for your help !
You never declare x and y outside of your draw() method, so they are not visible to addTuioObject(). If you need values from inside the draw method, you could declare class fields instead like you did with cursor_size or object_size. Use
int x, y;
outside of any methods and then assign accordingly, or add parameters to your addTuioObject() method:
void addTuioObject(TuioObject tobj, int x, int y) {
// Your code
}