I am trying to extend a java fx Canvas:
package com.kavricious.math;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import java.util.Random;
public class LPlotCanvas extends Canvas{
boolean grid = false;
boolean axes = true;
boolean ticks = true;
boolean startDrawn = false;
double xMin;
double xMax;
double yMin;
double yMax;
int density;
short canvasWidth = 800;
short canvasHeight = 800;
byte colorIndex = 0;
private GraphicsContext gc = null;
public LPlotCanvas(double xmin,double xmax, double ymin, double ymax){
xMin = xmin;
xMax = xmax;
yMin = ymin;
yMax = ymax;
density = 100;
setWidth(canvasWidth);
setHeight(canvasHeight);
gc = getGraphicsContext2D();
drawStart();
}
private void drawStart(){
System.out.println("drawing start");
if(gc == null)System.out.println("it null");
gc.setLineWidth(2);
gc.setStroke(Color.BLACK);
if(axes){
if(xMin<0.0&&xMax>0.0){
drawLine(gc,0,yMin-1,0,yMax+1);
}
if(yMin<0.0&&yMax>0.0){
drawLine(gc,xMin-1,0,xMax+1,0);
}
}
if(grid){
for(int i =(int)((xMin>0)?Math.floor(xMin):Math.ceil(xMin));i<xMax+1;i++){
gc.setLineWidth(0.25);
drawLine(gc,i,yMin,i,yMax);
}
for(int i =(int)((yMin>0)?Math.floor(yMin):Math.ceil(yMin));i<yMax+1;i++){
gc.setLineWidth(0.25);
drawLine(gc,xMin,i,xMax,i);
}
}
startDrawn = true;
}
public void showGrid(boolean b){
grid = b;
}
public void showAxes(boolean b){
axes = b;
}
public void showTicks(boolean b){
ticks = b;
}
public void setCanvasWidth(short width){
this.canvasWidth = width;
}
public void setCanvasHeight(short height){
this.canvasHeight = height;
}
private void plotPoint(double x,double y,Color color){
if(!startDrawn)drawStart();
gc.setFill(color);
gc.fillOval(convertX(x),convertY(y),5,5);
}
public void drawPolynomial(LPolynomial function)throws Exception{
if(!startDrawn)drawStart();
gc.setStroke(getNextColor(colorIndex));
double start = xMin;
double step = (xMax-xMin)/density;
for(int i=0;i<density;i++){
drawLine(gc,start+step*i,function.evaluateAt(start+step*i),start+step*(i+1),function.evaluateAt(start+step*(i+1)));
}
colorIndex++;
}
private void drawLine(GraphicsContext gc,double x1,double y1,double x2, double y2){
int nx1 = convertX(x1);
int ny1 = convertY(y1);
int nx2 = convertX(x2);
int ny2 = convertY(y2);
gc.strokeLine(nx1,ny1,nx2,ny2);
System.out.println("line drawn");
}
private int convertX(double in){
double widthOfPixel = (xMax-xMin)/canvasWidth;//how much space on the real number line is put into one pixel
return (int) Math.floor((in-xMin)/widthOfPixel);//how much greater than left side DIVIDED by pixel size -> how many pixels away from left side
}
private int convertY(double in){
double heightOfPixel = (yMax-yMin)/canvasHeight;
return canvasHeight - (int) Math.floor((in-yMin)/heightOfPixel);
}
public Color getNextColor(byte i){
switch(i){
case 0: return Color.rgb(255,0,0);//red
case 1: return Color.rgb(0,200,0);//lime
case 2: return Color.rgb(0,0,235);//blue
case 3: return Color.rgb(255,255,0);//yellow
case 4: return Color.rgb(255,50,255);//magenta/fuchsia
case 5: return Color.rgb(255,165,0);//orange
case 6: return Color.rgb(0,235,235);
case 7: return Color.rgb(107,30,119);
case 8: return Color.rgb(0,100,0);
default: Random rand = new Random();
int r = rand.nextInt(256);
int g = rand.nextInt(256);
int b = rand.nextInt(256);
return Color.rgb(r,g,b);
}
}
}
and then call it in another application:
package com.kavricious.math;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.shape.ArcType;
import java.util.ArrayList;
public class LPlotter2 extends Application{
private ArrayList<LPolynomial> functions;
public static void main(String[] args){
launch(args);
}
#Override
public void start(Stage ps){
this.functions = new ArrayList<LPolynomial>();
LPolynomial[] funcs = new LPolynomial[]{new LPolynomial(2.3,3.4,2.2,1.1),new LPolynomial(0,1,-2.3),new LPolynomial(1,2),new LPolynomial(2,2,2.3,1,0.4)};
for(LPolynomial f: funcs){
this.functions.add(f);
}
ps.setTitle("LPlotter");
StackPane layout = new StackPane();
LPlotCanvas canv = new LPlotCanvas(-10,10,-10,10);
for(LPolynomial function : functions){
try{
canv.drawPolynomial(function);
}catch(Exception e){System.out.println("an exception wad caught");e.printStackTrace();}
}
layout.getChildren().add(canv);
ps.setScene(new Scene(layout,800,800));
ps.show();
}
}
(In the above code I have tried putting the for loop that draws the polynomials in every position possible after the LPlotCanvas is initialized, and the same result occurs.)
but then I run it and see nothing:
This is what it should look like (created without extension).
So what is wrong?
Related
I'm working on a school assignment where I am supposed to create a maze from a textfile. My problem is creating the maze. I know it's probably an easy fix, but I am really stuck and need to get this done.. Any suggestions?
package application;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import javafx.application.Application;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
public class Main extends Application {
LabyrintRute[][] Labyrint;
int X;
int Y;
int startx;
int starty;
Spiller spilleren;
int sizeX;
int sizeY;
#Override
public void start(Stage primaryStage) {
try {
GridPane root = new GridPane();
Spiller spilleren = new Spiller(startx, starty);
filLeser();
root.add(spilleren.getUtseende(), spilleren.getxPossisjon(), spilleren.getyPossisjon());
for(int x = 0; x<X; x++){
for(int y = 0; y<Y; y++){
root.add(Labyrint[x][y].getUtseende(), x, y);
}
}
Scene scene = new Scene(root, X*10, Y*10);
scene.setOnKeyPressed(new FilLytter(this));
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public void filLeser() {
String teksten = "";
File fila;
int rad = 0;
FileChooser filvelger = new FileChooser();
filvelger.setTitle("Åpne en tekstfil");
filvelger.getExtensionFilters().add(new ExtensionFilter("Text Files", "*.txt"));
fila = filvelger.showOpenDialog(null);
try (Scanner filleser = new Scanner(fila)) {
X = filleser.nextInt();
Y = filleser.nextInt();
teksten = filleser.nextLine();
Labyrint = new LabyrintRute [X][Y];
while (filleser.hasNext()) {
teksten = filleser.nextLine();
for (int i = 0;i< X;i++) {
char tegn = teksten.charAt(i);
switch (tegn) {
case '#':
Labyrint[i][rad] = new Vegg(i, rad);
break;
case ' ':
Labyrint[i][rad] = new Gang(i, rad);
break;
case '-':
Labyrint[i][rad] = new Utgang(i, rad);
break;
case '*':
Labyrint[i][rad] = new Gang(i, rad);
startx = i;
starty = rad;
break;
}
rad++;
}
}
} catch (FileNotFoundException e) {
System.out.println("Kan ikke åpne fila!");
e.printStackTrace();
}
}
public void flyttSpiller(int deltax, int deltay) {
int nyx = spilleren.getxPossisjon() + deltax;
int nyy = spilleren.getyPossisjon() + deltay;
Labyrint[nyx][nyy].flyttHit(spilleren);
}
public static void main(String[] args) {
launch(args);
}
}
The "Vegg"(wall) class:
package application;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
public class Vegg extends LabyrintRute {
private Node utseende;
public Vegg(int xKoordinat, int yKoordinat) {
super(xKoordinat, yKoordinat);
utseende = new Rectangle(10, 10, Color.MEDIUMPURPLE);
}
#Override
public void flyttHit(Spiller spilleren) {
//spilleren.setxPossisjon(getxKoordinat());
//spilleren.setyPossisjon(getyKoordinat());
}
#Override
public Node getUtseende() {
return utseende;
}
}
Abstract class:
package application;
import javafx.scene.Node;
public abstract class LabyrintRute {
private int xKoordinat;
private int yKoordinat;
public LabyrintRute(int xKoordinat, int yKoordinat) {
this.xKoordinat = xKoordinat;
this.yKoordinat = yKoordinat;
}
public int getxKoordinat() {
return xKoordinat;
}
public int getyKoordinat() {
return yKoordinat;
}
public abstract void flyttHit(Spiller spilleren);
public abstract Node getUtseende();
}
I also have a "Gang" (passage), and a "Utgang" (exit) class. They are similiar to the "Vegg" class.
Would really appreciate inputs! Sorry for the norwegian code..
When you read the file and create the lab, your variable rad is incremented in a loop that goes to from 0 to X-1. However, you use it to index the Y dimension. If X > Y, you will run out of bounds there.
Since your code does not fully reveal the rules of the file and how the lab can be formed,I cannot provide a fix directly.
I think you most probably need some kind of nested loop. Maybe you should keep and increment i with the nextLine's and have the inner loop somehow like for (int rad = 0; rad < Y; rad++) but again, it's impossible for me to say without further inside.
This question already has answers here:
Create a Trailing line of blood behind a player
(2 answers)
Closed 6 years ago.
I have a program that takes information on two planets/bodies in space and animates their orbits around each other realistically. It works, though when I repaint, it clears the screen each time and does not leave a trail.
My problem is that I want to leave a trail, though any answer I can find online only explains how to get rid of a trail. However, I don't have that problem.
On other computers, I can leave out the super.paintComponent() in my paint method and that causes it to leave a trail, but on this computer, it doesn't do that, it seems to clear the screen automatically. So then how can I efficiently draw a trail behind my orbiting planets? My code follows.
JPanel class first:
import javax.swing.*;
import java.awt.*;
/**
* Created by chris on 3/2/16.
*/
public class SpacePanel2 extends JPanel{
private Body2[] planets;
public static final Dimension SCREENSIZE = Toolkit.getDefaultToolkit().getScreenSize();
public static double scale = 5e6; //m/p
public static Color[] colors = {Color.black, Color.red};
public SpacePanel2(Body2[] planets) {
this.planets = planets;
this.setPreferredSize(SCREENSIZE);
}
#Override
public void paint(Graphics g){
for (int i = 0; i < planets.length; i++) {
g.setColor(colors[i]);
int r = planets[i].getPixelRadius()/2;
int x = planets[i].getPixelX();
int y = planets[i].getPixelY();
g.fillOval(x, y, r, r);
}
}
}
Body class:
/**
* Created by chris on 3/2/16.
*/
public class Body2 {
private double mass; //in kilograms
private double radius; //in meters
private static final double GRAVITATIONAL_CONSTANT = 6.67408e-11;
private static final double AVERAGE_DENSITY = 5515; //kg/m^3
/**
* Movement variables
*/
private double dx; //in m/s
private double dy; //in m/s
private double x; //in m
private double y; //in m
public Body2() {
radius = 1;
mass = AVERAGE_DENSITY;
x = 0;
y = 0;
dx = 0;
dy = 0;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getMass() {
return mass;
}
public double getRadius() {
return radius;
}
public int getPixelX() {
return (int)((this.x-radius)/SpacePanel2.scale);
}
public int getPixelY() {
return (int)((this.y-radius)/SpacePanel2.scale);
}
public int getPixelRadius(){
return (int)(this.radius/SpacePanel2.scale);
}
public void setMass(double mass) {
this.mass = mass;
}
public void setRadius(double radius) {
this.radius = radius;
}
public void setDx(double dx) {
this.dx = dx;
}
public void setDy(double dy) {
this.dy = dy;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public void exertForce2(double diffY, double diffX, double F){
double dist = Math.sqrt(diffY*diffY + diffX*diffX);
double ratio = F / dist;
this.dy = this.dy + ratio*diffY/this.mass;
this.dx = this.dx + ratio*diffX/this.mass;
}
public void tick(double timeScale) {
x+=(dx/1000.0)*timeScale;
y+=(dy/1000.0)*timeScale;
}
public static double getForce(Body2 a, Body2 b){
double dX = a.getX() - b.getX();
double dY = a.getY() - b.getY();
double distance = Math.sqrt(Math.pow(dX,2)+Math.pow(dY,2));
return (a.getMass()*b.getMass()*GRAVITATIONAL_CONSTANT)/(distance*distance);
}
public static double getStandardMass(double radius){
return (4.0/3.0)*Math.pow(radius, 3) * Math.PI;
}
public double getDy() {
return dy;
}
public double getDx() {
return dx;
}
public static double predictCentripetalForce(Body2 sun, Body2 planet){
return Math.sqrt(getForce(planet, sun)*(sun.getY()-planet.getY())/planet.mass);
}
}
Main class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
/**
* Created by chris on 3/2/16.
*/
public class MainSpace2 {
static JFrame frame;
static SpacePanel2 panel;
static int fps = 60;
static boolean getLarger = false;
static boolean getSmaller = false;
static Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
public static void main(String[] args) {
Body2[] test = new Body2[2];
Body2 sun = new Body2();
sun.setRadius(696300000);
sun.setMass(1.989e30);
sun.setX(getScope('x') / 2);
sun.setY(getScope('y') / 2);
sun.setDx(0);
sun.setDy(0);
test[0] = sun;
int literalSizeSun = (int)(sun.getRadius()/SpacePanel2.scale);
Body2 mercury = new Body2();
mercury.setRadius(24400000);
mercury.setMass(Body2.getStandardMass(mercury.getRadius()));
mercury.setDx(Body2.predictCentripetalForce(sun, mercury)*2);
mercury.setDy(0);
mercury.setX(sun.getX());
mercury.setY(sun.getY() + 2 * sun.getRadius());
test[1] = mercury;
int literalSizeMercury = (int)(mercury.getRadius()/SpacePanel2.scale);
frame = new JFrame();
frame.setPreferredSize(size);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new SpacePanel2(test);
frame.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyChar()) {
case '-':
getSmaller = true;
getLarger = false;
break;
case '=':
getLarger = true;
getSmaller = false;
break;
}
}
#Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyChar()) {
case '-':
getSmaller = false;
break;
case '=':
getLarger = false;
break;
}
}
});
double timeScale = 60*24;
Timer time = new Timer((int) (1000.0 / fps), new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
double F = Body2.getForce(test[0], test[1]);
double dY = test[1].getY() - test[0].getY();
double dX = test[1].getX() - test[0].getX();
test[0].exertForce2(dY, dX, F);
test[1].exertForce2(-dY, -dX, F);
for (int j = 0; j < test.length; j++) {
test[j].tick(timeScale);
}
panel.repaint(sun.getPixelX(), sun.getPixelY(), literalSizeSun, literalSizeSun);
panel.repaint(mercury.getPixelX(), mercury.getPixelY(), literalSizeMercury, literalSizeMercury);
}
});
frame.add(panel);
frame.pack();
frame.setVisible(true);
time.start();
}
public static double getScope(char k) {
switch (k) {
case 'x':
return size.width * SpacePanel2.scale;
case 'y':
return size.height * SpacePanel2.scale;
default:
return 0;
}
}
}
Custom painting is done by overriding the paintComponent() method, not paint().
if you leave a continuous trail, once you do a 360 rotation you won't see any more animation, so I would think you need to clear the screen eventually.
If you want to leave a trail you can keep an ArrayList of Objects you want to paint. Then in the paintComponent() method you can iterate through the List. This will allow you to add/remove Object from the list so you can control the number of Objects you want to paint each animation.
Check out the DrawOnComponent example from Custom Painting Approaches for an example of this approach. So your animation logic would basically add a new Object (and potentially remove one once you reach a certain limit?) to the List. Then you just invoke repaint() on the panel and all the Objects will be painted.
You already have List to paint each planet. So each animation you would need to add the new location of each planet to the List.
Or, the link shows how you can paint to a BufferedImage. But this approach doesn't allow you to remove a painting once it is done. So it depends an your exact requirement which approach you use.
How do you make a java single player version of agario? I would like to use Object Oriented Programming. So there should be Dot, Blob, and a Controller Object.
(I just want to share my code so don't vote down :)
I made it this way. There is the dots with random color, blob that starts as 20 size. A thread check every couple milliseconds for collision.
Dot:
package agario;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.util.Random;
public class Dot extends Component{
public int x;
public int y;
public Color c;
public int size;
Dot(int x, int y){
this.x = x;
this.y = y;
Random rand = new Random();
int r = rand.nextInt(255);
int green = rand.nextInt(255);
int b = rand.nextInt(255);
this.c = new Color(r,green,b);
this.size = rand.nextInt(50);
}
public void paint(Graphics g){
g.setColor(c);
g.fillOval(this.x, this.y, this.size, this.size);
}
}
Blob:
package agario;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
public class Blob extends Component{
public int x;
public int y;
public int size;
public Color color;
public static Blob blob = new Blob(800,100,40,Color.blue);
Blob(int x, int y, int size, Color c){
this.x = x;
this.y = y;
this.size = size;
this.color = c;
}
public void paint(Graphics g){
g.setColor(color);
g.fillOval(x, y, size, size);
}
}
Controller:
package agario;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Label;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
public class Controller {
ArrayList<Blob> blobs = new ArrayList<Blob>();
public ArrayList<Dot> dots = new ArrayList<Dot>();
Blob b = new Blob(50,50,10,Color.CYAN);
MyFrame mf = new MyFrame("Agario");
Label l = new Label("10");
int mouseX = 0;
int mouseY = 0;
static int score = 30;
static int xDis = 0;
static int yDis = 0;
public static void main(String[] args){
new Controller().startGame();
}
public void startGame(){
mf.addMouseMotionListener(new MyMouseMoveListener());
mf.add(l,BorderLayout.NORTH);
Refresh rf = new Refresh();
Thread t = new Thread(rf);
t.start();
while(true){
try{
Random r = new Random();
Thread.sleep(r.nextInt(40));
double dis = Math.sqrt(xDis*xDis + yDis*yDis);
double easingAmount = 20;
b.x += xDis / easingAmount;
b.y += yDis / easingAmount;
if(r.nextInt(10) == 5){
int randX = r.nextInt(600);
int randY = r.nextInt(600);
Dot d = new Dot(randX,randY);
synchronized(dots){
dots.add(d);
}
mf.add(d);
mf.repaint();
}
}catch(Exception e){
}
}
}
class Refresh implements Runnable{
public void run() {
while(true){
Random ran = new Random();
try{
Thread.sleep(ran.nextInt(20));
}catch(Exception e){
System.out.println("error");
}
Rectangle r = new Rectangle(b.x,b.y,b.size,b.size);
synchronized(dots){
Iterator i = dots.iterator();
while(i.hasNext()){
Dot d = (Dot) i.next();
Rectangle r1 = new Rectangle(d.x,d.y,d.size,d.size);
if(r1.intersects(r)){
i.remove();
b.size += 1;
l.setText(String.valueOf(Integer.parseInt(l.getText())+1));
score += 1;
}
}
}
mf.repaint();
}
}
}
class MyMouseMoveListener extends MouseMotionAdapter{
public void mouseMoved(MouseEvent m){
mouseX = m.getX();
mouseY = m.getY();
xDis = mouseX-b.x;
yDis = mouseY-b.y;
}
}
class MyFrame extends Frame{
MyFrame(String s){
super(s);
setBounds(0,0,900,900);
add(b);
blobs.add(b);
setVisible(true);
}
public void paint(Graphics g){
for(Blob b : blobs)
b.paint(g);
synchronized(dots){
Iterator i = dots.iterator();
while(i.hasNext()){
Dot d = (Dot) i.next();
d.paint(g);
}
}
}
}
}
I stumbled upon a problem: if an image is moving at a high speed across the screen it is rendered incorrectly producing a ghosting effect. I think we can rule out my monitor being the problem as this type of movement was flawless in swing (with the same framerate).
Looks like:
Code (merged from 3 classes):
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import java.awt.Dimension;
import java.awt.Toolkit;
public class Constructor extends Application{
Image player, shot;
static Dimension screen = new Dimension(Toolkit.getDefaultToolkit().getScreenSize());
static int wid = screen.width;
static int hei = screen.height;
static boolean up, down, left, right, rotleft , rotright;
static double x = (wid/2)-109;
static double y = (hei/1.5)-132;
static double velx = 0, vely = 0, velx2 = 0, vely2 = 0;
static double forspeed = 0, sidespeed = 0;
static int rotat = 0;
public void load(){
player = new Image("res/sprite.png");
}
#Override
public void start(final Stage frame) throws Exception{
load();
frame.setTitle("DEFAULT");
frame.initStyle(StageStyle.UNDECORATED);
Group root = new Group();
final ImageView ship = new ImageView();
ship.setImage(player);
root.getChildren().add(ship);
frame.setScene(new Scene(root, wid, hei, Color.BLACK));
frame.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>(){
public void handle(KeyEvent key) {
if(key.getCode()==KeyCode.W)
up = true;
if(key.getCode()==KeyCode.S)
down = true;
if(key.getCode()==KeyCode.Q)
left = true;
if(key.getCode()==KeyCode.E)
right = true;
if(key.getCode()==KeyCode.A)
rotleft = true;
if(key.getCode()==KeyCode.D)
rotright = true;
}
});
frame.addEventHandler(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>(){
public void handle(KeyEvent key) {
if(key.getCode()==KeyCode.ESCAPE)
{
frame.close();
System.exit(0);
}
if(key.getCode()==KeyCode.W)
up = false;
if(key.getCode()==KeyCode.S)
down = false;
if(key.getCode()==KeyCode.Q)
left = false;
if(key.getCode()==KeyCode.E)
right = false;
if(key.getCode()==KeyCode.A)
rotleft = false;
if(key.getCode()==KeyCode.D)
rotright = false;
}
});
frame.setAlwaysOnTop(true);
frame.setHeight(hei);
frame.setWidth(wid);
frame.setResizable(false);
frame.setFullScreen(true);
frame.show();
new AnimationTimer() {
#Override
public void handle(long now) {
gameloop();
ship.setTranslateX(x);
ship.setTranslateY(y);
ship.setRotate(rotat);
}
}.start();
}
public static void gameloop(){
if(Shared.up)
forspeed += 1;
if(Shared.down)
forspeed -= 1;
if(Shared.right)
sidespeed += 1;
if(Shared.left)
sidespeed -= 1;
if(Shared.rotleft)
rotat -=3;
if(Shared.rotright)
rotat +=3;
velx = Math.cos(Math.toRadians(rotat-90))*forspeed + Math.cos(Math.toRadians(rotat))*sidespeed;
vely = Math.sin(Math.toRadians(rotat-90))*forspeed + Math.sin(Math.toRadians(rotat))*sidespeed;
if(!Shared.up && !Shared.down)
{
if(forspeed > 0)
forspeed -= 0.2;
else if (forspeed < 0)
forspeed += 0.2;
}
if(!Shared.right && !Shared.left)
{
if(sidespeed > 0)
sidespeed -= 0.2;
else if (sidespeed < 0)
sidespeed += 0.2;
}
x += velx;
y += vely;
screencolisions();
}
private static void screencolisions() {
// LEFT RIGHT
if(x < 0)
{
x = 0;
sidespeed = 0;
}
else if (x+218 > Shared.wid)
{
x = Shared.wid-218;
sidespeed = 0;
}
// UP DOWN
if(y < 0)
{
y = 0;
forspeed = 0;
}
else if (y+164 > Shared.hei)
{
y = Shared.hei-164;
forspeed = 0;
}
}
public static void main(String[] args){
Application.launch(args);
}
}
Well first thing is you are using AWT classes in Javafx .. They are not friends (most of the time).
Instead of using Dimension and the AWT toolkit,
Use the provided Javafx Screen class
Screen screen = Screen.getPrimary();
wid = screen.getBounds().getWidth();
hei = screen.getBounds().getHeight();
// Visual bounds will be different depending on OS and native toolbars etc..
// think of it as desktop bounds vs whole screen
For example:
public class ScreenBounds extends Application {
#Override
public void start(Stage primaryStage) {
Screen screen = Screen.getPrimary();
System.out.println("ScreenBounds : " + screen.getBounds() + "\nVisualBounds : " + screen.getVisualBounds());
Platform.exit();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
prints:
compile-single:
run-single:
ScreenBounds : Rectangle2D [minX = 0.0, minY=0.0, maxX=1680.0, maxY=1050.0, width=1680.0, height=1050.0]
VisualBounds : Rectangle2D [minX = 0.0, minY=40.0, maxX=1680.0, maxY=1050.0, width=1680.0, height=1010.0]
As you can see no Syntax error as you described..
Though that error is probably due to your variables being Integers not Doubles like the method returns;
ScheduledService Timer:
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.util.Duration;
/**
*
* #author jdub1581
*/
public class NanoTimer extends ScheduledService<Void> {
private final long ONE_NANO = 1000000000L;
private final double ONE_NANO_INV = 1f / 1000000000L;
private long startTime, previousTime;
private double frameRate, deltaTime;
private final NanoThreadFactory tf = new NanoThreadFactory();
public NanoTimer() {
super();
this.setPeriod(Duration.millis(16));// equivalent to 60 fps
this.setExecutor(Executors.newCachedThreadPool(tf));
}
public double getTimeAsSeconds() {
return getTime() * ONE_NANO_INV;
}
public long getTime() {
return System.nanoTime() - startTime;
}
public long getOneSecondAsNano() {
return ONE_NANO;
}
public double getFrameRate() {
return frameRate;
}
public double getDeltaTime() {
return deltaTime;
}
private void updateTimer() {
deltaTime = (getTime() - previousTime) * (1.0f / ONE_NANO);
frameRate = 1.0f / deltaTime;
previousTime = getTime();
}
#Override
public void start() {
super.start();
if (startTime <= 0) {
startTime = System.nanoTime();
}
}
#Override
public void reset() {
super.reset();
startTime = System.nanoTime();
previousTime = getTime();
}
private boolean init = true;
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
updateTimer();
// perform NON UI calculations here
return null;
}
};
}
#Override
protected void succeeded() {
super.succeeded();
//update the UI here
}
#Override
protected void failed() {
getException().printStackTrace(System.err);
}
#Override
public String toString() {
return "ElapsedTime: " + getTime() + "\nTime in seconds: " + getTimeAsSeconds()
+ "\nFrame Rate: " + getFrameRate()
+ "\nDeltaTime: " + getDeltaTime();
}
/*==========================================================================
creates a daemon thread for use
*/
private class NanoThreadFactory implements ThreadFactory {
public NanoThreadFactory() {
}
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "NanoTimerThread");
t.setDaemon(true);
return t;
}
}
}//=============================================================================
Whatever class you put it in, just call the start method, probably best nested as a private class so variable can be used inside of it.. Or rewrite as you need..
I use it here: My Cloth Simulation and it works well doing 50k+ calculations per frame
I believe the code will speak for itself, but in general the point of the code is the have a Map class that will take in an array of BufferedImages, x values, and y values, to compose a map of many layers (first layer being the BufferedImage array at 0, starting at the x value at 0 and the y value at 0, and so on). The main job of the map class, is to take each pixel of each image and convert them to Block Objects, which are just simply rectangles with a color (Includes a BufferedImage, because after it works, I will replace the color with the Image. Also includes an integer to specify which layer (1 being index 0) its allowed on with 0 meaning it can exist among all layers). In the end, when I call Render() on a Map object, the map object should do all the work in rendering the blocks into the correct positions. The largest problem with all of this is that I get no sytax or compiler errors, so my logic is what is messed up and I can not figure it out!
Thanks in advance, and if the question is confusing please tell me!
The Map Class:
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
public class Map {
private int width;
private int height;
public int getWidth() { return width; }
public int getHeight() { return height; }
private int xPos;
private int yPos;
public int getX(int i)
{
return xPos;
}
public int getY(int i)
{
return yPos;
}
public void setPosition(int x, int y) { xPos = x; yPos = y; }
private int[] xStarts;
private int[] yStarts;
private ArrayList<BufferedImage> layersList = new ArrayList<BufferedImage>();
public void addLayer(BufferedImage image) { layersList.add(image); }
public void setLayer(int i, BufferedImage image) { layersList.set(i, image); }
private Block[][][] blocksArray;
private boolean beenInitialized = false;
public Map(BufferedImage[] images, int[] x, int[] y){
for (BufferedImage image : images){
layersList.add(image);
xStarts = x;
yStarts = y;
}
}
public void initialize(){
int widthMax = 0;
int heightMax = 0;
for (BufferedImage image : layersList){
if (image.getHeight() > heightMax) { heightMax = image.getHeight(); }
if (image.getWidth() > widthMax) { widthMax = image.getWidth(); }
}
width = widthMax;
height = heightMax;
blocksArray = new Block[layersList.size()][width][height];
for (int i = 0; i < layersList.size(); i++){
int currentLayer = i;
for (int y = 0; y < layersList.get(i).getHeight(); y++){
for (int x = 0; x < layersList.get(i).getWidth(); x++){
int colorCode = layersList.get(i).getRGB(x, y);
boolean error = true;
Block b = null;
for (int c = 0; c < Block.BLOCKS.size(); c++){
if (Block.BLOCKS.get(i).getColorCode() == colorCode && (Block.BLOCKS.get(i).getLayerCode() == currentLayer || Block.BLOCKS.get(i).getLayerCode() == 0)){
b = Block.BLOCKS.get(c);
error = false;
}
}
if (!error){
blocksArray[currentLayer][x][y] = b;
} else {
Block bb = new Block(false, colorCode);
bb.initialize();
blocksArray[currentLayer][x][y] = bb;
}
}
}
}
beenInitialized = true;
}
public void render(Graphics2D g2d){
if (beenInitialized){
for (int i = 0; i < layersList.size(); i++){
for (int y = yStarts[i]; y < layersList.get(i).getHeight() + yStarts[i]; y += Block.SIZE){
int currentY = 0;
for (int x = xStarts[i]; x < layersList.get(i).getWidth() + xStarts[i]; x += Block.SIZE){
int currentX = 0;
blocksArray[i][currentX][currentY].setPosition(x, y);
blocksArray[i][currentX][currentY].render(g2d);
currentX ++;
}
currentY++;
}
}
}
}
public void updatePosition(int x, int y){
xPos += x;
yPos += y;
}
}
The Block Class:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
public class Block {
public static final int SIZE = 32;
public static final boolean DEBUG = true;
public static ArrayList<Block> BLOCKS = new ArrayList<Block>();
private Color debugColor;
public Color getColor() { return debugColor; }
public void setColor(Color color) { debugColor = color; }
private BufferedImage blockIcon;
public BufferedImage getIcon() { return blockIcon; }
public void setIcon(BufferedImage icon) { blockIcon = icon; }
private int xPos;
private int yPos;
public int getX() { return xPos; }
public int getY() { return yPos; }
public void setPosition(int x, int y) { xPos = x; yPos = y; }
private Rectangle blockShape;
public Rectangle getShape() { return blockShape; }
private int colorCode;
public int getColorCode() { return colorCode; }
private boolean colides;
public boolean doesColide() { return colides; }
private int layerCode;
public int getLayerCode() { return layerCode; }
private boolean beenInitialized = false;
public Block(boolean colides, int layerCode){
this.colides = colides;
this.layerCode = layerCode;
}
public void initialize(){
blockShape = new Rectangle(xPos, yPos, SIZE, SIZE);
int r = (colorCode >> 16) & 0x000000FF;
int g = (colorCode >> 8) & 0x000000FF;
int b = (colorCode) & 0x000000FF;
debugColor = new Color(r, g, b);
BLOCKS.add(this);
beenInitialized = true;
}
public void render(Graphics2D g2d){
if (beenInitialized){
if (DEBUG){
g2d.setColor(debugColor);
if (colides){
g2d.fill(blockShape);
} else {
g2d.draw(blockShape);
}
} else{
}
}
}
}
And finally the Game Class (I threw this together JUST to show a window for testing):
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Game extends JFrame{
public Game(){
super("Test");
try{
layer1 = ImageIO.read(getClass().getResourceAsStream("/layer1.png"));
layer2 = ImageIO.read(getClass().getResourceAsStream("/layer2.png"));
} catch (Exception ex) { ex.printStackTrace(); }
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setLayout(new BorderLayout());
add(new panel(), BorderLayout.CENTER);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args){
new Game();
}
private int[] xStartPositions = {0, 0};
private int[] yStartPositions = {0, 0};
private BufferedImage layer1;
private BufferedImage layer2;
private BufferedImage[] imageArray = {layer1, layer2};
private Map map;
public class panel extends JPanel{
public panel(){
setMinimumSize( new Dimension(1200, 675));
setMaximumSize( new Dimension(1200, 675));
setPreferredSize( new Dimension(1200, 675));
setVisible(true);
map = new Map(imageArray, xStartPositions, yStartPositions);
}
public void paint(Graphics g){
Graphics2D g2d = (Graphics2D) g;
map.render(g2d);
}
}
}
The initialize method of Map is never called, therefore Map will never render...
Some feedback...
Don't ever override paint, use paintComponent instead (it's very rare that you would need to override paint...
Make sure you are calling super.paintXxx - there's a lot of important working going on in the background that you don't want to miss or replicate...
Instead of extending from a top level container like JFrame, start by extending from JPanel and add this to a frame you create instead
Beware of static variables, this might cause you more problems ;)
You may also want to have a read through Initial Threads