javafx and serializability - file-io

In the old AWT libraries, the Point class and the Color class were serializable. Neither is in JavaFX. I would like to save an array list of Drawables to a file; here is the interface
import javafx.scene.canvas.GraphicsContext;
public interface Drawable
{
public void draw(GraphicsContext g);
}
When I attempt to to this, I get bombarded by NotSerializableExceptons.
What is the best alternate course of action? All of my drawables know their color and size.

Use a custom serializable form and serialize the data you need. E.g.
import javafx.scene.canvas.GraphicsContext ;
import javafx.scene.paint.Color ;
import javafx.geometry.Rectangle2D;
import java.io.Serializable ;
import java.io.ObjectInputStream ;
import java.io.ObjectOutputStream ;
import java.io.IOException ;
public class DrawableRect implements Drawable, Serializable {
private transient Color color ;
private transient Rectangle2D bounds ;
public DrawableRect(Color color, Rectangle2D bounds) {
this.color = color ;
this.bounds = bounds ;
}
#Override
public void draw(GraphicsContext g) {
g.setFill(color);
g.fillRect(bounds.getMinX(), bounds.getMinY(), bounds.getWidth(), bounds.getHeight());
}
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
// write color:
s.writeDouble(color.getRed());
s.writeDouble(color.getGreen());
s.writeDouble(color.getBlue());
s.writeDouble(color.getOpacity());
// write bounds:
s.writeDouble(bounds.getMinX());
s.writeDouble(bounds.getMinY());
s.writeDouble(bounds.getWidth());
s.writeDouble(bounds.getHeight());
}
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
double r = s.readDouble();
double g = s.readDouble();
double b = s.readDouble();
double opacity = s.readDouble();
color = new Color(r,g,b,opacity);
double x = s.readDouble();
double y = s.readDouble();
double w = s.readDouble();
double h = s.readDouble();
bounds = new Rectangle2D(x,y,w,h);
}
}
If you have fields that are serializable (or primitive types), you don't mark them transient, and the defaultReadObject and defaultWriteObject will handle them. If you have fields that are not serializable, mark them transient and serialize the data in a form that can be serialized as in the example.
Obviously, since you have multiple implementations of this interface which may all need this functionality, it might benefit you to create a helper class with some static methods:
public class DrawableIO {
public static void writeColor(Color color, ObjectOutputStream s) throws IOException {
s.writeDouble(color.getRed());
s.writeDouble(color.getGreen());
s.writeDouble(color.getBlue());
s.writeDouble(color.getOpacity());
}
public static Color readColor(ObectInputStream s) throws IOException {
double r = s.readDouble();
double g = s.readDouble();
double b = s.readDouble();
double opacity = s.readDouble();
return new Color(r,g,b,opacity);
}
public static void writeBounds(Rectangle2D bounds, ObjectOutputStream s) throws IOException {
s.writeDouble(bounds.getMinX());
s.writeDouble(bounds.getMinY());
s.writeDouble(bounds.getWidth());
s.writeDouble(bounds.getHeight());
}
public static Rectangle2D readBounds(ObjectInputStream s) throws IOException {
double x = s.readDouble();
double y = s.readDouble();
double w = s.readDouble();
double h = s.readDouble();
return new Rectangle2D(x,y,w,h);
}
}
and then of course the methods in your Drawable implementations reduce to something like
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
DrawableIO.writeColor(color, s);
DrawableIO.writeBounds(bounds, s);
}
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
color = DrawableIO.readColor(s);
bounds = DrawableIO.readBounds(s);
}

Related

Unable to identify where a NullPointerException is coming from

so I am getting the following error:
Exception in thread "Thread-0" java.lang.NullPointerException
at dev.tamir.firstgame.entities.creatures.Player.getInput(Player.java:19)
at dev.tamir.firstgame.entities.creatures.Player.tick(Player.java:31)
at dev.tamir.firstgame.states.GameState.tick(GameState.java:25)
at dev.tamir.firstgame.Game.tick(Game.java:65)
at dev.tamir.firstgame.Game.run(Game.java:110)
at java.lang.Thread.run(Unknown Source)
And I've checked all the lines Java had marked me and I can not find what is producing the null.
Player:
package dev.tamir.firstgame.entities.creatures;
import java.awt.Graphics;
import dev.tamir.firstgame.Game;
import dev.tamir.firstgame.gfx.Assets;
public class Player extends Creature {
private Game game;
public Player(Game game, float x, float y) {
super(game, x, y, Creature.DEFAULT_CREATURE_WIDTH, Creature.DEFAULT_CREATURE_HEIGHT);
}
#Override
public void tick() {
getInput();
move();
game.getGameCamera().centerOnEntity(this);
}
private void getInput() {
xMove = 0;
yMove = 0;
if(game.getKeyManager().up)
yMove = -speed;
if(game.getKeyManager().down)
yMove = speed;
if(game.getKeyManager().left)
xMove = -speed;
if(game.getKeyManager().right)
xMove = speed;
}
#Override
public void render(Graphics g) {
g.drawImage(Assets.robro[7], (int) (x - game.getGameCamera().getxOffset()), (int) (y - game.getGameCamera().getyOffset()), width, height, null);
}
}
Gamestate:
package dev.tamir.firstgame.states;
import java.awt.Graphics;
import dev.tamir.firstgame.Game;
import dev.tamir.firstgame.entities.creatures.Player;
import dev.tamir.firstgame.tiles.Tile;
import dev.tamir.firstgame.worlds.World;
public class GameState extends State {
private Player player;
private World world;
public GameState(Game game) {
super(game);
player = new Player(game, 0, 0);
world = new World(game, "res/worlds/world1.txt");
}
#Override
public void tick() {
world.tick();
player.tick();
}
#Override
public void render(Graphics g) {
world.render(g);
player.render(g);
}
}
Game:
package dev.tamir.firstgame;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import dev.tamir.firstgame.Display.Display;
import dev.tamir.firstgame.gfx.Assets;
import dev.tamir.firstgame.gfx.GameCamera;
import dev.tamir.firstgame.input.KeyManager;
import dev.tamir.firstgame.states.GameState;
import dev.tamir.firstgame.states.MenuState;
import dev.tamir.firstgame.states.State;
public class Game implements Runnable {
private Display display;
private Thread thread;
private BufferStrategy bs;
private Graphics g;
//States
private State gameState;
private State menuState;
//Input
private KeyManager keyManager;
//Camera
private GameCamera gameCamera;
private boolean running = false;
private int width, height;
public String title;
public Game(String title, int width, int height) {
this.width = width;
this.height = height;
this.title = title;
keyManager = new KeyManager();
}
private void init() {
display = new Display(title, width, height);
display.getFrame().addKeyListener(keyManager);
Assets.init();
gameCamera = new GameCamera(this, 0,0);
gameState = new GameState(this);
menuState = new MenuState(this);
State.setState(gameState);
}
private void tick() {
keyManager.tick();
if(State.getState() != null)
State.getState().tick();
}
private void render() {
bs = display.getCanvas().getBufferStrategy();
if(bs == null) {
display.getCanvas().createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
//Clear
g.clearRect(0, 0, width, height);
//Draw
if(State.getState() != null)
State.getState().render(g);
//End of Draw
bs.show();
g.dispose();
}
public void run() {
init();
int fps = 60;
double timePerTick = 1000000000 / fps;
double delta = 0;
long now;
long lastTime = System.nanoTime();
long timer = 0;
int ticks = 0;
while (running) {
now = System.nanoTime();
delta += (now - lastTime) / timePerTick;
timer += now - lastTime;
lastTime = now;
if(delta >= 1) {
tick();
render();
ticks++;
delta--;
}
if(timer >= 1000000000) {
System.out.println("FPS: " + ticks );
ticks = 0;
timer = 0;
}
}
stop();
}
public KeyManager getKeyManager() {
return keyManager;
}
public GameCamera getGameCamera() {
return gameCamera;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public synchronized void start() {
if (running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
public synchronized void stop() {
if (!running)
return;
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
help would be very appreciated, as I've been looking for hours now and I don't know what is causing the null and I am suspecting the error log may even be misleading me.
My guess would be you have a private Game in your creature class. When you call super() in Player, you pass a Game object to Creature. The Creature constructor most likely has a line like this.game = game;
Of course, I can't say for sure because the Creature class is not included in your post, but that's the most likely code setup. Because game would then be private to Creature, Player cannot see it. That means the private Game game that you declare in Player is never set.
After you call super, do this.game = game;
This will almost certainly take care of your issue.
Just for future reference, the message you got when the error resulted is the call stack; basically it tells you what methods called what, the most recent being at the top. The error took place at line 19 in Player.getInput(), which was called by tick() in that same class.
The only object you use in getInput() is game, and so that must be the source of the null pointer. From there, it's a quick check to see that game is a private field of Player, and since it is null that's a huge clue that it was never initialized (though that is not always the case). Private fields most often are initialized in the class constuctor (but they don't have to be... your Player class is pretty sparse so it wouldn't take that long to look through all of it if you absolutly had to. Looking at the Player constructor, we see a Game object named game is passed in, which suggests that it was intended to be used to initialize game and yet never is. Voilà, we found the problem!
I'm sorry if that last paragraph felt a little condecending; it wasn't meant to be. I just wanted to walk you through how I found your issue. Hopefully knowing how I found it will help you find later errors on your own.

How to draw several lines slowly in constant velocity on canvas by Android?

I need capture the mark to draw a figure on canvas in Android, and the effect just like the follow gif:
Well, as far, I can draw a side with constant velocity by ValueAnimator. However, I just only can draw one side at one time, because I can't save the last side when drawing the next side. So, is there a good way to solve the problem?
Code for draw a line slowly by ValueAnimator:
GraphicsView.java
public class GraphicsView extends View {
private int stepX, stepY = 0;
private int startX, startY, stopX, stopY = 0;
private Paint paint = null;
public GraphicsView(Context context) {
super(context);
// Paint
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
startX = 40;
startY = 397;
stopX = 1040;
stopY = 397;
Init();
}
public void Init(){
ValueAnimator animatorX = ValueAnimator.ofFloat(startX, stopX);
ValueAnimator animatorY = ValueAnimator.ofFloat(startY, stopY);
animatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
stepX = Math.round((Float)valueAnimator.getAnimatedValue()); invalidate();
}
});
animatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
stepY = Math.round((Float)valueAnimator.getAnimatedValue()); invalidate();
}
});
AnimatorSet set = new AnimatorSet();
LinearInterpolator l = new LinearInterpolator();
set.setInterpolator(l);
set.setDuration(3000);
set.playTogether(animatorX, animatorY);
set.start();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(startX, startY, stepX, stepY, paint);
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Display display = null;
private GraphicsView view = null;
private ConstraintLayout layout = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
display = getWindowManager().getDefaultDisplay();
layout = (ConstraintLayout)findViewById(R.id.main_layout);
view = new GraphicsView(this);
view.setMinimumWidth(display.getWidth());
view.setMinimumHeight(display.getHeight());
layout.addView(view);
}
}
you can use the ObjectAnimator class to callback
to one of your class methods every time you'd like to draw a bit more of the path.
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.view.View;
import android.util.Log;
public class PathView extends View
{
Path path;
Paint paint;
float length;
public PathView(Context context)
{
super(context);
}
public PathView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public PathView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
}
public void init()
{
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
path = new Path();
path.moveTo(50, 50);
path.lineTo(50, 500);
path.lineTo(200, 500);
path.lineTo(200, 300);
path.lineTo(350, 300);
// Measure the path
PathMeasure measure = new PathMeasure(path, false);
length = measure.getLength();
float[] intervals = new float[]{length, length};
ObjectAnimator animator = ObjectAnimator.ofFloat(PathView.this, "phase", 1.0f, 0.0f);
animator.setDuration(3000);
animator.start();
}
//is called by animtor object
public void setPhase(float phase)
{
Log.d("pathview","setPhase called with:" + String.valueOf(phase));
paint.setPathEffect(createPathEffect(length, phase, 0.0f));
invalidate();//will calll onDraw
}
private static PathEffect createPathEffect(float pathLength, float phase, float offset)
{
return new DashPathEffect(new float[] { pathLength, pathLength },
Math.max(phase * pathLength, offset));
}
#Override
public void onDraw(Canvas c)
{
super.onDraw(c);
c.drawPath(path, paint);
}
}
Then, just call init() to begin the animation, like this (or if you'd like it to start as soon as the view is inflated, put the init() call inside the constructors):
PathView path_view = (PathView) root_view.findViewById(R.id.path);
path_view.init();
Also see this question here, and
Using Value Animator Example
Reference 1
Reference 2
Reference 3

Libgdx - camera.unproject is not fixing my coordinates

The following code gives me very strange y coordinates.
10-18 00:13:36.834 30543-30567/com.xxxx.yyyy.android I/x﹕ 137.4782
10-18 00:13:36.834 30543-30567/com.xxxx.yyyy.android I/y﹕ -1984.2426
10-18 00:13:36.835 30543-30567/com.xxxx.yyyy.android I/ux﹕ 91.65213
10-18 00:13:36.835 30543-30567/com.xxxx.yyyy.android I/uy﹕ -1984.2426
I imagine I set up everything wrong rather than do it wrong while running?
The camera.unproject call should take care of all remapping from screen coordinates to game coordinates, shouldn't it? Or do i have to scale and invert before unprojecting?
package com.xxxx.yyyy;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
public class LetterActor extends Actor
{
private Texture texture;
private Vector3 touchPosition = new Vector3();
private Camera camera;
private boolean unproject = true;
public LetterActor(Texture letterTexture, Camera theCamera)
{
texture = letterTexture;
camera = theCamera;
touchPosition.set(240, 800, 0);
camera.unproject(touchPosition);
setPosition(touchPosition.x, touchPosition.y);
setSize(texture.getWidth(), texture.getHeight());
addListener(new InputListener()
{
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
touchPosition.set(x, y, 0);
if (unproject)
{
camera.unproject(touchPosition);
}
setPosition(touchPosition.x, touchPosition.y);
logPositions(x, y, touchPosition.x, touchPosition.y);
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button)
{
touchPosition.set(x, y, 0);
if (unproject)
{
camera.unproject(touchPosition);
}
setPosition(touchPosition.x, touchPosition.y);
logPositions(x, y, touchPosition.x, touchPosition.y);
}
#Override
public void touchDragged(InputEvent event, float x, float y, int pointer)
{
touchPosition.set(x, y, 0);
if (unproject)
{
camera.unproject(touchPosition);
}
setPosition(touchPosition.x, touchPosition.y);
logPositions(x, y, touchPosition.x, touchPosition.y);
}
});
}
private void screenTo()
{
}
private void logPositions(float x, float y,float ux, float uy)
{
Gdx.app.log("x", Float.toString(x));
Gdx.app.log("y", Float.toString(y));
Gdx.app.log("ux", Float.toString(ux));
Gdx.app.log("uy", Float.toString(y));
}
#Override
public void draw(Batch batch, float alpha)
{
batch.draw(texture, getX(), getY(), getWidth(), getHeight());
}
#Override
public void act(float delta) {}
}
package com.xxxx.yyyy;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.utils.viewport.ExtendViewport;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.utils.viewport.FitViewport;
public class WordPuzzle extends ApplicationAdapter
{
private final static float VIRTUAL_WIDTH = 480;
private final static float VIRTUAL_HEIGHT = 800;
private OrthographicCamera camera;
private FitViewport viewport;
private Stage stage;
#Override
public void create()
{
camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
camera.setToOrtho(false, VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
viewport = new FitViewport(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, camera);
stage = new Stage();
stage.setViewport(viewport);
Gdx.input.setInputProcessor(stage);
Texture[] textures = LetterLoader.loadLetters();
for (int i = 0; i < textures.length; i++)
{
LetterActor letterActor = new LetterActor(textures[i], camera);
letterActor.setTouchable(Touchable.enabled);
stage.addActor(letterActor);
}
}
#Override
public void render()
{
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
#Override public void resize(int width, int height)
{
stage.getViewport().update(width, height, true);
}
#Override public void dispose()
{
stage.dispose();
}
}
package com.xxxx.yyyy;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
public class LetterLoader {
public static Texture[] loadLetters()
{
Texture[] letters = new Texture[26];
for (int i = 0; i < 26; i++)
{
char letter = (char) (i + 65);
letters[i] = new Texture(Gdx.files.internal("bigletters/" + letter + ".png"));
}
return letters;
}
}
First, the touch position (x, y) you get from the input listener are already the correct coordinates.
Concerning your output, you actually print y two times, but call it uy the second time:
Gdx.app.log("uy", Float.toString(y));
If touchPosition.set(240, 800, 0); is in screen coordinates, then you need to unproject them, but
camera.unproject(touchPosition);
assumes that your camera fills the whole screen, thus it calls internally:
unproject(screenCoords, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Since you use a virtual size, this is wrong. The most simple solution would be to use the unproject method from the viewport that you are using:
viewport.unproject(touchPosition);
This will call the camera unproject method with the correct parameters automatically.
Since you are using Stage and InputListener, the coordinates you get in touchDown and the related methods are already in world coordinates, so it doesn't make sense to unproject them. You can use the x and y directly.
Also (although this is irrelevant to InputListener), camera.unproject assumes a Viewport that fills the screen, which is not true of FitViewport, which you're using. If you are using a Viewport class, you need to use viewport.unproject instead of camera.unproject, so it takes the black bars into account.
But you only need to worry about unprojecting for stuff not related to the Stage.

Method to check if number is contained in ArrayList will not work, NullPointerExcepton. Can you use ArrayList method inside a constructed method?

This is a project I am working on and it is supposed to take input from the user then which is an area code then see if it is contained in a array list. My method that I have created will not work in another class and I am not sure why, it is returning a NullPointerException.
The NullPointerException is shown at this line of code: if (mountainTime.contains(input))
This is the class with methods
package finalPro;
import java.util.ArrayList;
public class Final
{
public Final()
{
input = 0;
timezone = 0;
}
public void checkIfTrue(int y)
{
input = y;
if (mountainTime.contains(input))
{
timezone = 1;
}
else
timezone = 0;
System.out.println(timezone);
}
public int getZone()
{
return timezone;
}
public ArrayList<Integer> mountainTime;
private int input;
private int timezone;
}
Here is test class
package finalPro;
import java.util.ArrayList;
import javax.swing.JOptionPane;
public class FinalLogic
{
public static void main(String[] args)
{
ArrayList<Integer> mountainTime = new ArrayList<Integer>();
mountainTime.add(480);
mountainTime.add(602);
mountainTime.add(623); //Arizona area codes
mountainTime.add(928);
mountainTime.add(520);
mountainTime.add(303);
mountainTime.add(719); //Colorado
mountainTime.add(720);
mountainTime.add(970);
mountainTime.add(406); //Montana
mountainTime.add(505); //New Mexico
mountainTime.add(575);
mountainTime.add(385);
mountainTime.add(435); //Utah
mountainTime.add(801);
mountainTime.add(307); //Wyoming
Final myMap = new Final();
{
String x = JOptionPane.showInputDialog("Please enter a number: ");
int input = Integer.parseInt(x);
myMap.checkIfTrue(input);
}
}
}
I hope it's not too late, I haven't done anything special to fix your code, just some movement of code,
Removed the initialization logic from class FinalLogic to Final class .(btw Final name is not really good, you might be aware final is reserved word in Java. Although your name is case sensitive but still)
package finalPro;
import javax.swing.JOptionPane;
public class FinalLogic {
public static void main(String[] args) {
Final myMap = new Final();
String x = JOptionPane.showInputDialog("Please enter a number: ");
int input = Integer.parseInt(x);
myMap.checkIfTrue(input);
}
}
And here is your class Final
package finalPro;
import java.util.ArrayList;
public class Final {
public Final() {
input = 0;
timezone = 0;
// moved all initialization logic to constructor
mountainTime = new ArrayList<>();
mountainTime.add(480);
mountainTime.add(602);
mountainTime.add(623); // Arizona area codes
mountainTime.add(928);
mountainTime.add(520);
mountainTime.add(303);
mountainTime.add(719); // Colorado
mountainTime.add(720);
mountainTime.add(970);
mountainTime.add(406); // Montana
mountainTime.add(505); // New Mexico
mountainTime.add(575);
mountainTime.add(385);
mountainTime.add(435); // Utah
mountainTime.add(801);
mountainTime.add(307); // Wyoming
}
public void checkIfTrue(int y) {
input = y;
if (mountainTime.contains(input)) {
timezone = 1;
} else
timezone = 0;
System.out.println(timezone);
}
public int getZone() {
return timezone;
}
public ArrayList<Integer> mountainTime;
private int input;
private int timezone;
}
I tried in my workspace, it gives no NPE, Hope it helps.

Problems with KeyListener and JOGL

I'm trying to bind a key to translate a GL_QUAD around the screen. I created a class, as I will attach below, that implements KeyListener, and within that I have a method that upon the keypress of 'd', adds 0.1 to the x coordinates of the quad vertices. Now, I have two questions relating to this.
Firstly, it doesn't seem to do anything. Upon the keypress, nothing happens to the object.
Is there a better way to achieve what I am trying to do? My end goal is to eventually end up with a sprite, that the camera is focused upon, that can move around a visually 2D game world.
Thanks for your time.
Code:
SpriteTest.java
package com.mangostudios.spritetest;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.FPSAnimator;
public class SpriteTest
{
public static void main(String[] args) {
GLProfile glp = GLProfile.getDefault();
GLCapabilities caps = new GLCapabilities(glp);
GLCanvas canvas = new GLCanvas(caps);
Frame frame = new Frame("AWT Window Test");
frame.setSize(300, 300);
frame.add(canvas);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
canvas.addGLEventListener(new Renderer());
FPSAnimator animator = new FPSAnimator(canvas, 60);
//animator.add(canvas);
animator.start();
}
}
Renderer.java
package com.mangostudios.spritetest;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
public class Renderer implements GLEventListener {
InputListener input = new InputListener();
#Override
public void display(GLAutoDrawable drawable) {
update();
render(drawable);
}
#Override
public void dispose(GLAutoDrawable drawable) {
}
#Override
public void init(GLAutoDrawable drawable) {
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {
}
private void update() {
}
private void render(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
// draw a triangle filling the window
gl.glBegin(GL2.GL_QUADS);
gl.glVertex2f( input.xTran, 0.1f);
gl.glVertex2f( input.xTran,-0.1f);
gl.glVertex2f( -input.xTran, -0.1f);
gl.glVertex2f( -input.xTran, 0.1f);
gl.glEnd();
}
}
InputListener.java
package com.mangostudios.spritetest;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
public class InputListener implements KeyListener{
boolean loopBool = false;
float xTran = 0.1f;
float yTran = 0.1f;
#Override
public void keyPressed(KeyEvent d) {
loopBool = true;
while (loopBool = true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void keyReleased(KeyEvent d) {
}
}
At first, you never call addKeyListener(). Secondly, you shouldn't put an infinite loop into keyPressed(). Thirdly, you use a NEWT KeyListener whereas you use an AWT GLCanvas :s Rather use GLWindow with a NEWT KeyListener or use an AWT GLCanvas with an AWT KeyListener or use NewtCanvasAWT. Finally, before writing your own example, try mine on Wikipedia in order to understand why it works.