im triying to create a simple game, where my player, falls into different platforms. However, rigth now, im only able to detect the first collision.
I've tried making a loop, where i call HandleEvent(), but only works for the first platform.
How could i make it to detect every time the player collides with a platform? Thank you!
Player class:
package com.mygdx.juegoreto;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Rectangle;
import java.util.ArrayList;
public class Personaje {
int x;
int y;
int width;
int height;
int xSpeed;
int ySpeed;
Color color;
public Personaje(int x, int y, int width, int height, int xSpeed, int ySpeed) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
this.color = Color.WHITE;
}
public void setxSpeed(int xSpeed) {
this.xSpeed = xSpeed;
}
public void setySpeed(int ySpeed) {
this.ySpeed = ySpeed;
}
public void update() {
x += xSpeed;
y += ySpeed;
if (x < 0 || x > Gdx.graphics.getWidth() - 70) {
xSpeed = -xSpeed;
}
if (y > Gdx.graphics.getHeight()) {
System.out.println("tas muerto");
}
}
public void draw(ShapeRenderer shape) {
shape.rect(x, y, width, height);
}
public void checkCollision(ArrayList<Plataforma> plats) {
if(collidesWith(plats)){
color = Color.GREEN;
}
else{
color = Color.WHITE;
}
}
private boolean collidesWith(ArrayList<Plataforma> plats) {
System.out.println("collides");
for (Plataforma plat : plats) {
if(x < plat.x + plat.width && y < plat.y + plat.height && x + width > plat.x && y + height > plat.y){
this.setySpeed(plat.ySpeed);
System.out.println("si");
return true;
}else{
this.setySpeed(-3);
System.out.println("no");
return false;
}
}
return true;
}
}
Main class:
package com.mygdx.juegoreto;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.graphics.GL20;
import java.util.ArrayList;
public class MyGame extends ApplicationAdapter {
ShapeRenderer shape;
Personaje player;
Plataforma plat;
ArrayList<Plataforma> plats;
private float timeSeconds = 0f;
private float period = 0f;
#Override
public void create () {
int x = Gdx.graphics.getWidth() / 2;
int y = Gdx.graphics.getHeight() ;
shape = new ShapeRenderer();
player = new Personaje(x, y - 200, 70, 70, 0, 0);
plat = new Plataforma(x - 70, y - 800, 200, 20,2);
plats = new ArrayList<>(1);
int altura = 0;
for(int i = 0; i <= 1 ; i++){
altura -= 160;
plats.add(new Plataforma((int)(Math.random() * Gdx.graphics.getWidth()), altura, 200, 20, 2));
}
}
#Override
public void render () {
ScreenUtils.clear(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
player.update();
//plat.update();
shape.begin(ShapeRenderer.ShapeType.Filled);
player.draw(shape);
//plat.draw(shape);
timeSeconds +=Gdx.graphics.getDeltaTime();
if(timeSeconds > period){
timeSeconds-=period;
handleEvent();
}
shape.end();
if (Gdx.input.isTouched()) {
if (Gdx.input.getX() < Gdx.graphics.getWidth() / 2){
player.setxSpeed(-2); //IZQUIERDA
} else {
player.setxSpeed(2); //DERECHA
}
}
if(player.y < -40){
System.out.println("tas muerto je");
}
/*for (Plataforma plat : plats ) {
int x = (int)(Math.random() * Gdx.graphics.getWidth());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(x);
plat.draw(shape);
}*/
}
#Override
public void dispose () {
}
public void handleEvent() {
for (Plataforma plataforma : plats) {
plataforma.update();
plataforma.draw(shape);
}
player.checkCollision(plats);
}
}
Let me be brief. I am creating a n-body simulation for a school-project. I've encountered a problem: I get the error IndexOutOfBoundsException only sometimes when I run the simulation. There does not seem to be any correlation between when I get the error. I am assuming I am destroying the bodies (via the collision detection method) too quickly for it to register, and it tries to access an index that no longer exists. I thought
if(bodies.get(i)!=null&&bodies.get(n)!= null)
in the update method would fix it, but it did not. Could someone take a look at the code and tell me what might be causing the error? To recreate the error: Simply press 'o' in the simulation, or randomly spawn massive bodies with 'm' until it occurs. Please keep in mind that I am only in high school, and I have not got a lot of programming experience.
MAIN:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main extends JPanel implements Runnable, KeyListener{
public static int width = 1400;
public static int height = (width/16) * 9;
public String title = "Orbital Mechanics Simulator -";
public Dimension dim = new Dimension(width, height);
public boolean running;
Color bgColor = new Color(0x000000);
public static long timeScale = (long) Math.pow(10,7.5); //how many simulation-seconds one IRL-second represents.
public static long distanceScale = ((Physics.astUnit*10L) / width); //how many meters does one pixel represent
ArrayList<Body> bodies = new ArrayList<Body>();
long initFpsTime;
long secondFpsTime;
long nowTime;
long lastTime;
long timeElapsed;
float deltaTime;
int fps = 200;
public Main(){
this.setPreferredSize(dim);
this.setBackground(bgColor);
this.start();
}
public void start(){
running = true;
Thread program = new Thread(this, "update");
program.start();
}
public void run(){
lastTime = System.nanoTime();
while(running){
nowTime = System.nanoTime();
deltaTime = nowTime - lastTime;
update(deltaTime);
initFpsTime = System.currentTimeMillis();
if((initFpsTime - secondFpsTime) > Math.pow(10,3) / fps){
render();
secondFpsTime = System.currentTimeMillis();
}
}
}
public void update(float deltaTime){
for(int i=0; i<bodies.size();i++){
resetForces();
bodies.get(i).update((float)(deltaTime / Math.pow(10,9))*timeScale);
lastTime = System.nanoTime();
//sets the forces for all bodies
for(int n=0; n<bodies.size();n++){
if(bodies.get(i)!=bodies.get(n)){
if(bodies.get(i)!=null&&bodies.get(n)!= null)
bodies.get(i).setForce(Physics.getFx(bodies.get(i), bodies.get(n)), Physics.getFy(bodies.get(i), bodies.get(n)));
//collision detection
if(Physics.getDistanceBetween(bodies.get(i), bodies.get(n)) < (bodies.get(i).radius + bodies.get(n).radius)*distanceScale){
collision(bodies.get(i),bodies.get(n));
}
}
}
}
}
//DIFFERENT SYSTEMS
public void solarSystem(){
Body sun;
Body earth;
Body mars;
sun = new Body("Sun", Physics.massSun, 20, 0,0, new Color(0xffff00), (float)0, (float)0);
earth = new Body("earth", Physics.massEarth, 10, Physics.astUnit/distanceScale,0, new Color(0x0000ff), (float)0, (float)0);
mars = new Body("Mars", Physics.massEarth, 10, (long)(1.5*Physics.astUnit/distanceScale) ,0, new Color(0x00ff00), (float)0, (float)0);
earth.setVelocity(0,(float)Physics.getInitVy((long)Physics.getDistanceBetween(earth, sun), sun));
mars.setVelocity(0,(float)Physics.getInitVy((long)Physics.getDistanceBetween(mars, sun), sun));
bodies.add(sun);
bodies.add(earth);
bodies.add(mars);
}
public void twoBodies(){
bodies.add(new Body("Sun", Physics.massSun, 20, 0,0, new Color(0xffff00), (float)0, (float)0));
bodies.add(new Body("earth", Physics.massEarth, 10, Physics.astUnit/distanceScale,0, new Color(0x0000ff), (float)0, (float)0));
bodies.add(new Body("Mars", Physics.massMars, 10, (long)(1.5*Physics.astUnit/(distanceScale)),0 ,new Color(0x00ff00), (float)0, (float)0));
//earth.setVelocity(0,(float)Physics.getInitVy((long)Physics.getDistanceBetween(earth, sun), sun));
//mars.setVelocity(0,(float)Physics.getInitVy((long)Physics.getDistanceBetween(mars, sun), sun));
}
public void createRandomBody(){
bodies.add(new Body("randomBody",Physics.massSun,10, Physics.randomXPos(), Physics.randomYPos(), Physics.randomColor(),(float)0,(float)0));
}
public void createMassiveBody(){
bodies.add(new Body("Sun",Physics.massSun,10, Physics.randomXPos(), Physics.randomYPos(), Physics.randomColor(),(float)0,(float)0));
}
public void createSmallBody(){
bodies.add(new Body("Earth",Physics.massEarth,10, 0, 0, Physics.randomColor(), (float)0, (float)0));
}
public void createSystem(){
for(int i=0; i<20;i++){
for(int n=0; n<20;n++){
bodies.add(new Body("Random", Physics.massSun, 4, -width/2 + n*20 , height/2 - i*20 , Color.WHITE, (float)0, (float)0 ));
}
}
}
public void resetForces(){
if(bodies.get(0) != null);
for(int i=0;i<bodies.size();i++){
if(i<=0 && i < bodies.size()){
bodies.get(i).resetForce();
}
}
}
public void collision(Body a, Body b){
Body newBody = new Body("newBody", a.mass+b.mass, 20, (a.xPos+b.xPos)/2, (a.yPos+b.yPos)/2, Physics.randomColor(), (a.mass*a.vx + b.mass*b.vx)/(a.mass+b.mass), (a.mass*a.vy+b.mass*b.vy)/(a.mass+b.mass));
bodies.remove(a);
bodies.remove(b);
bodies.add(newBody);
}
public void render(){
repaint();
}
public void keyPressed(KeyEvent event) {
switch(event.getKeyChar()){
case 'r': createRandomBody();
break;
case 'f': twoBodies();
break;
case 'm':
createMassiveBody();
break;
case 'z':
createSmallBody();
break;
case 'o':
createSystem();
break;
case 's':
solarSystem();
break;
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); //quick vs quality - preferring quality
for(int i=0;i<bodies.size();i++){
bodies.get(i).displayPlanet(g2d);
}
}
public static void gui(){
Main main = new Main();
JFrame frame = new JFrame();
frame.setResizable(false);
frame.setTitle(main.title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(main);
frame.addKeyListener(main);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]){
SwingUtilities.invokeLater(new Runnable(){ //Event dispatching thread
public void run(){
gui();
}
});
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
BODY
import java.awt.Color;
import java.awt.Graphics;
public class Body {
public static int xOrigo = Main.width / 2;
public static int yOrigo = ((Main.width * 9) / 16) / 2;
public static int numOfBodies; // how many bodies the program contains.
public static float distanceScale = Main.distanceScale;
public String name;
public float mass, fx, fy, accX, accY, vx, vy, initVx, initVy, deltaX, deltaY;
public long xDisplay, yDisplay;
public long xPos, yPos;
public int radius;
public Color color;
public Body(String name, float mass, int radius, long xPos, long yPos, Color color, float initVx, float initVy){
this.name = name;
this.mass = mass;
this.radius = radius;
this.color = color;
numOfBodies++;
setX(xPos);
setY(yPos);
setVelocity(initVx, initVy);
}
public void update(float deltaTime){
this.deltaX += this.vx * deltaTime;
if(this.deltaX >= distanceScale){
this.incX();
deltaX = 0;
}else if(this.deltaX <= -distanceScale){
this.decX();
deltaX = 0;
}
this.deltaY += this.vy * deltaTime;
if(this.deltaY >= distanceScale){
this.incY();
deltaY = 0;
}else if(this.deltaY <= -distanceScale){
this.decY();
deltaY = 0;
}
this.vx += (this.accX * deltaTime);
this.vy += (this.accY * deltaTime);
}
public void setX(long xPos){
this.xPos = xPos;
this.xDisplay = xOrigo + xPos - radius;
}
public void setY(long yPos){
this.yPos = yPos;
this.yDisplay = yOrigo - yPos - radius;
}
public void incX(){
this.xPos++;
this.xDisplay = xOrigo + xPos - radius;
}
public void decX(){
this.xPos--;
this.xDisplay = xOrigo + xPos - radius;
}
public void incY(){
this.yPos++;
this.yDisplay = yOrigo - yPos - radius;
}
public void decY(){
this.yPos--;
this.yDisplay = yOrigo - yPos - radius;
}
public void setForce(float fx, float fy){
this.fx += fx;
this.accX = fx / this.mass;
this.fy += fy;
this.accY = fy / this.mass;
}
public void setVelocity(float vx, float vy){
this.vx += vx;
this.vy += vy;
}
public void displayPlanet(Graphics g){
g.setColor(this.color);
g.fillOval((int )this.xDisplay, (int)this.yDisplay, this.radius*2, this.radius*2); //temporary fix
}
public long getXPos(){
return this.xPos;
}
public long getYPos(){
return this.yPos;
}
public void resetForce(){
this.fx = 0;
this.fy = 0;
}
}
PHYSICS:
import java.awt.Color;
import java.util.Random;
public class Physics {
public static Random rand = new Random();
public static final double G = 6.67384*(Math.pow(10, -11));
public static long astUnit = 149597871000L; //L IS TO INDICATE IT'S A LONG VALUE, otherwise neg value
public static float massEarth = (float)(5.97219*Math.pow(10,24));
public static float massSun = (float)(1.9891*Math.pow(10,30));
public static float massMars = (float) (6.41693*(Math.pow(10,23)));
public static float randomMass(){
return (float) Math.pow(((rand.nextDouble()*(massSun-massEarth))),rand.nextDouble())+massEarth;
}
public static double randInitV(){
return (double) rand.nextDouble()*Math.pow(10,4);
}
public static int randomXPos(){
return rand.nextInt(Main.width)-Main.width/2;
}
public static int randomYPos(){
return rand.nextInt(Main.height)-Main.height/2;
}
public static Color randomColor(){
return new Color(rand.nextInt(0xffffff));
}
public static int randomRadius(){
return rand.nextInt(50)+5;
}
public Physics(){
}
/*
public static Vector getVectorBetween(Body a, Body b){
float force = (float)((G*a.mass*b.mass) / Math.pow(getDistanceBetween(a,b),2));
double angle = Math.atan2(Math.abs(a.y - b.y),Math.abs(a.x - b.x));
Vector vector = new Vector(force,angle);
return vector;
}
*/
public static double getInitVy(long d, Body a){
return Math.sqrt((G*a.mass) / d);
}
public static float getFx(Body a, Body b){
float force = getForceBetween(a,b);
double angle = getAngleBetween(a,b);
float fx = (float)(force*Math.cos(angle));
if(a.xPos > b.xPos){
return -fx;
}else{
return fx;
}
}
public static float getFy(Body a, Body b){
float force = getForceBetween(a,b);
double angle = getAngleBetween(a,b);
float fy = (float)(force*Math.sin(angle));
if(a.yPos > b.yPos){
return -fy;
}else{
return fy;
}
}
public static float getForceBetween(Body a, Body b){
float force = (float)((G*a.mass*b.mass) / Math.pow(getDistanceBetween(a,b),2));
return force;
}
public static double getDistanceBetween(Body a, Body b){
double xKatet = Math.abs(a.getXPos()*Main.distanceScale - b.getXPos()*Main.distanceScale);
double yKatet = Math.abs(a.getYPos()*Main.distanceScale - b.getYPos()*Main.distanceScale);
double distance = Math.hypot(xKatet, yKatet);
return distance;
}
public static double getAngleBetween(Body a, Body b){
long deltaX = Math.abs(a.xPos-b.xPos);
long deltaY = Math.abs(a.yPos-b.yPos);
double angle = Math.atan2(deltaY, deltaX);
return angle;
}
}
(Given the few information and the wall of code, I may be going too far out on a limb, but in doubt, I can delete the answer)
You are accessing the same list with different threads. The collision handling method
public void collision(Body a, Body b) {
...
bodies.remove(a);
bodies.remove(b);
bodies.add(newBody);
}
is executed by the main physics thread that is started in the Main#start() method. This thread is modifying the list. And this may happen while the Swing Event Dispatch Thread (that is also reponsible for painting) is iterating over the bodies in the paintComponent method:
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
...
for(int i=0;i<bodies.size();i++){
bodies.get(i).displayPlanet(g2d);
}
}
Adding additional checks will not solve this issue. You'll need some form of synchronization. The brute-force-hammer would be to just synchronize on the bodies list:
public void collision(Body a, Body b) {
...
synchronized (bodies)
{
bodies.remove(a);
bodies.remove(b);
bodies.add(newBody);
}
}
and
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
...
synchronized (bodies)
{
for(int i=0;i<bodies.size();i++){
bodies.get(i).displayPlanet(g2d);
}
}
}
(basically, something like this would have to be done in all places where one thread might read the list while another thread is writing to the list).
But again: This is rather pragmatic. You could consider one of the thread-safe data structures from the java.util.concurrent package, or some manual, more fine-grained locking solution, probably with some ReadWriteLock.
It's far too much code to give a more focussed answer here (but at least, I wanted to point out what is (almost certainly) the reason for your problem)
You have a problem in your method Main.update(), the essentials of which are:
public void update(float deltaTime){
for(int i=0; i<bodies.size();i++){
// ...
//sets the forces for all bodies
for(int n=0; n<bodies.size();n++){
// ...
//collision detection
if(Physics.getDistanceBetween(bodies.get(i), bodies.get(n)) < (bodies.get(i).radius + bodies.get(n).radius)*distanceScale){
collision(bodies.get(i),bodies.get(n));
}
}
}
}
In the event that i is bodies.size() - 1 and there is a collision with another body, the two colliding bodies are replaced with a single body, reducing the total number of bodies by 1. At that point i is bodies.size(), which is not a valid index into bodies. You nevertheless continue the inner loop, during which you perform bodies.get(i) again, generating an IndexOutOfBoundsException.
I'm trying to fire a projectile in the mouse direction but i am having trouble.
The angles are wrong, and by that I mean it will only go up left or in the top-left corner.
This is my Gun class for which I fire the Bullet.
package assets;
import Reaper.Game;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
public class Gun
{
public ArrayList<Bullet> bullets;
protected double angle;
Mouse mouse = new Mouse();
private BufferedImage image;
private int centerX = Game.WIDTH / 2;
private int centerY = Game.HEIGHT;
public Gun()
{
bullets = new ArrayList<Bullet>();
image = null;
try
{
image = ImageIO.read(new File("assets/gun.png"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
public BufferedImage loadImage()
{
return image;
}
public int getImageWidth()
{
return image.getWidth(null);
}
public int getImageHeight()
{
return image.getHeight(null);
}
public void rotate(Graphics g)
{
angle = Math.atan2(centerY - mouse.getMouseY(), centerX - mouse.getMouseX()) - Math.PI / 2;
((Graphics2D) g).rotate(angle, centerX, centerY);
g.drawImage(image, Game.WIDTH / 2 - image.getWidth() / 2,
900 - image.getHeight(), image.getWidth(), image.getHeight(),
null);
}
public Image getImage()
{
return image;
}
public void update()
{
shoot();
for (int i = 0; i < bullets.size(); i++)
{
Bullet b = bullets.get(i);
b.update();
}
}
public void shoot()
{
if (mouse.mouseB == 1)
{
double dx = mouse.getMouseX() - Game.WIDTH / 2;
double dy = mouse.getMouseY() - Game.HEIGHT / 2;
double dir = Math.atan2(dy, dx);
bullets.add(new Bullet(Game.WIDTH / 2, Game.HEIGHT / 2, dir));
mouse.mouseB = -1;
}
}
public void render(Graphics g)
{
for (int i = 0; i < bullets.size(); i++)
{
bullets.get(i).render(g);
}
rotate(g);
}
}
This is my Bullet class:
package assets;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Bullet
{
private double dx, dy;
private int x, y;
private double dir;
private BufferedImage image;
public Bullet(int x, int y, double angle)
{
this.x = x;
this.y = y;
this.dir = angle;
image = null;
try
{
image = ImageIO.read(new File("assets/bolt.png"));
}
catch (IOException e)
{
e.printStackTrace();
}
dx = Math.cos(dir);
dy = Math.sin(dir);
}
public void update()
{
x += dx;
y += dy;
System.out.println("dx : " + dx + " " + dy);
}
public void render(Graphics g)
{
g.drawImage(image, x, y, image.getWidth(), image.getHeight(), null);
}
public BufferedImage getImage()
{
return image;
}
}
And this is the main Game class:
package Reaper;
import Reaper.graphics.Screen;
import assets.Gun;
import assets.Mouse;
import gameState.MenuState;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;
public class Game extends Canvas implements Runnable
{
private static final long serialVersionUID = 1L;
public static int WIDTH = 900;
public static int HEIGHT = 900;
public static int scale = 3;
public int frames = 0;
public int updates = 0;
private boolean running = false;
private Thread thread;
private JFrame frame;
#SuppressWarnings("unused")
private Screen screen;
private Gun gun;
private MenuState mns;
private Mouse mouse;
public Game()
{
Dimension size = new Dimension(WIDTH, HEIGHT);
setPreferredSize(size);
screen = new Screen(WIDTH, HEIGHT);
frame = new JFrame();
gun = new Gun();
mns = new MenuState();
mouse = new Mouse();
addMouseListener(mouse);
addMouseMotionListener(mouse);
}
public static void main(String[] args)
{
Game game = new Game();
game.frame.setResizable(false);
game.frame.add(game);
game.frame.pack();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setVisible(true);
game.frame.setLocationRelativeTo(null);
game.strat();
}
public void strat()
{
running = true;
thread = new Thread(this, "Reaper");
thread.start();
}
public void stop()
{
running = false;
try
{
thread.join();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public void run()
{
long timer = System.currentTimeMillis();
long lastTime = System.nanoTime();
double ns = 1000000000.0 / 60;
double delta = 0;
while (running)
{
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1)
{
update();
updates++;
delta--;
}
render();
frames++;
if (System.currentTimeMillis() - timer > 1000)
{
timer = System.currentTimeMillis();
frame.setTitle("Reaper! " + " | " + updates + " ups , " + frames + " fps");
updates = 0;
frames = 0;
}
}
stop();
}
public void update()
{
if (mns.play)
{
gun.update();
}
}
public void render()
{
BufferStrategy bs = getBufferStrategy();
if (bs == null)
{
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.fillRect(0, 0, WIDTH, HEIGHT);
if (mns.menu)
{
mns.draw(g);
}
if (mns.play)
{
g.clearRect(0, 0, WIDTH, HEIGHT);
g.drawImage(mns.getImage(), 0, 0, mns.getImageWidth(), mns.getImageHeight(), this);
gun.render(g);
}
if (mns.rules)
{
g.clearRect(0, 0, WIDTH, HEIGHT);
}
bs.show();
}
}
I know it's very badly coded, and I will try to fix it as much as I can, but I am really stuck on this. Searched around the web, tried some of the solutions but it wont work. I guess I'm doing it wrong by putting methods in wrong places and calling them, I guess.
I know it's very badly coded, and I will try to fix it as much as I can, ...
Next time, consider first cleaning up the mess and then asking the question.
(Are the variables storing the values returned by getMouseX() and getMouseY() really static?)
However, the main reason for the actual problem are the x and y values in the Bullet class:
class Bullet
{
private double dx, dy;
private int x, y;
....
public void update()
{
x += dx;
y += dy;
System.out.println("dx : " + dx + " " + dy);
}
...
}
They are declared as int values. Imagine what happens in the update method, for example, when x=0 and dx = 0.75: It will compute 0+0.75 = 0.75, truncate this to be an int value, and the result will be 0.
Thus, the x and y values will never change, unless the dx and dy values are >= 1.0, respectively.
Just changing the type of x and y to double will solve this. You'll have to add casts in the render method accordingly:
g.drawImage(image, (int)x, (int)y, ...);
But you should really clean this up.
I've started using LWJGL recently since I stopped using Java and wanted a quick refresher with something new tied in. Unfortunately, I've encountered a problem while working on a small Java pong game. I sort of sped through it, but I've reviewed my code multiple times and I cannot figure out what is wrong.
Problem: I can't update multiple entities on the screen at the same time. It is weird because I have no problem moving them, and their values update accordingly according to the debugger, but the graphics will not update on the screen. Here is my code for the main program:
package lwjgl2;
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
public class Main {
private Box ball = new Box(640>>1, 480>>1, 5, 5);
private Box paddle = new Box(10, 10, 10, 40);
private long lastTime;
private long getTime(){
return (Sys.getTime() * 1000) / Sys.getTimerResolution();
}
private int getDelta(){
long currentTime = getTime();
int delta = (int) (currentTime - lastTime);
lastTime = getTime();
return delta;
}
public Main() {
//display
try{
Display.setDisplayMode(new DisplayMode(640,480));
Display.setTitle("Hello");
Display.create();
} catch(LWJGLException e){
e.printStackTrace();
}
//ogl
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 640, 480, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
lastTime = getTime();
//main loop
while(!Display.isCloseRequested()){
glClear(GL_COLOR_BUFFER_BIT);
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
Display.destroy();
System.exit(0);
}
paddle.setDX(0.1);
ball.setDX(0.3);
ball.setDY(0.2);
//main game loop goes nyah
ball.update(getDelta());
paddle.update(getDelta());
ball.draw();
paddle.draw();
Display.update();
Display.sync(60);
}
//destroy display
Display.destroy();
}
private class Box extends Entity{
public Box(int x, int y, int height, int width) {
super(x, y, height, width);
// TODO Auto-generated constructor stub
}
public void update(int delta){
super.x += dx * delta;
super.y += dy * delta;
}
public void draw(){
glRecti(x, y, x + height, y + width);
}
}
public static void main(String args[]){
new Main();
}
}
Like I said, the only entity that will actually render properly on the screen is whatever I call the update() method on first, in this case, the ball. If I call the paddle first, then the paddle will move, but the ball will stay still. I know I must have made a stupid mistake somewhere but I can't find it.
Also, the Entity class, possibly the main culprit:
package lwjgl2;
import java.awt.Rectangle;
public abstract class Entity {
protected int x;
protected int y;
protected int height;
protected int width;
protected double dx;
protected double dy;
protected Rectangle bounds = new Rectangle();
public Entity(int x, int y, int height, int width) {
this.x = x;
this.y = y;
this.height = height;
this.width = width;
this.dx = 0;
this.dy = 0;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public double getDX(){
return dx;
}
public double getDY(){
return dy;
}
public void setX(int x){
this.x = x;
}
public void setY(int y){
this.y = y;
}
public void setDX(double dx){
this.dx = dx;
}
public void setDY(double dy){
this.dy = dy;
}
public void update(int delta){
}
public void draw(int delta){
}
}
I've figured it out. It happens that updating multiple entities at varying times through the loop isn't a good idea, so you should create a method for updating every entity at once.
Error: main method not found in class essence.Game, please define the main method as: public static void main(String[] args)
The code:
package essence;
import static org.lwjgl.opengl.GL11.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
import org.lwjgl.input.*;
import org.lwjgl.opengl.*;
import org.lwjgl.*;
public class Game{
List<Box> shapes = new ArrayList<Box>(16);
public Game(){
try {
Display.setDisplayMode(new DisplayMode(800,600));
Display.setTitle("Essence");
Display.create();
} catch (LWJGLException e){
e.printStackTrace();
}
shapes.add(new Box(15, 15));
shapes.add(new Box(100, 150));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 800, 600, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
while(!Display.isCloseRequested()){
glClear(GL_COLOR_BUFFER_BIT);
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
Display.destroy();
System.exit(0);
}
for (Box box : shapes) {
box.draw();
}
Display.update();
Display.sync(60);
}
Display.destroy();
}
private static class Box {
public boolean selected = false;
public int x, y;
private float colorRed, colorBlue, colorGreen;
Box (int x, int y){
this.x = x;
this.y = y;
Random randomGenerator = new Random();
colorRed = randomGenerator.nextFloat();
colorBlue = randomGenerator.nextFloat();
colorGreen = randomGenerator.nextFloat();
}
boolean inBounds(int mouseX, int mouseY){
if(mouseX > x && mouseX < x + 50 && mouseY > y && mouseY < y + 50)
return true;
else
return false;
}
void randomizeColors(){
Random randomGenerator = new Random();
colorRed = randomGenerator.nextFloat();
colorBlue = randomGenerator.nextFloat();
colorGreen = randomGenerator.nextFloat();
}
void update(int dx, int dy){
x += dx;
y += dy;
}
void draw(){
glColor3f(colorRed, colorGreen, colorBlue);
glBegin(GL_QUADS);
glVertex2f(x, y);
glVertex2f(x + 50, y);
glVertex2f(x + 50, y + 50);
glVertex2f(x, y + 50);
glEnd();
}
}
public static void main(String[] args) {
new Game();
}
}
Now let's say I change it to:
package essence;
public class Game{
public static void main(String[] args) {
}
}
It will still give the same error. I checked the folder layout, but I confirmed that its Eclipse\Data\workspace\Essence\src\essence and Eclipse\Data\workspace\Essence\bin\essence
It cannot be my Java installation, because all my other projects work fine. Here's a screenshot of the project within Eclipse:
http://gyazo.com/296d53b33fa2619ca300c8a896d097dc
What could be the cause of this error and the way to fix it?
It happens to me as well. Restarting the Compiler fix the problem. For Example, If you are running Eclipse, just restart Eclipse.