I am testing out a Player object in a game I am trying to build, and I have begun testing my input using a white rectangle on the screen through OpenGL in LWJGL.
The problem is that when I compile the code and try moving the rectangle using the arrow keys, the rectangle only responds to RIGHT and DOWN. When testing it out in the loop, it appears the dx and dy are changing in the move() method, but the change does not persist into the updateXY() method.
-SNIP- (jump problem has been fixed)
I am completely stumped as to why this could be and I would love to get some help
Thanks in advance
EDIT: Added the AbstractMoveableEntity class
EDIT: Updated the code to reflect the current problem
public class Player extends AbstractMoveableEntity implements MoveableEntity {
MouseHandler m;
private double tx, ty;
private double SPEED;
private enum DIR{
UP, DOWN, LEFT, RIGHT;
}
public Player(double x, double y, MouseHandler m) {
super(x, y, 50, 50);
this.m = m;
this.tx = x;
this.ty = y;
this.ax = 0;
this.ay = 0;
this.SPEED = 5;
}
public void draw() {
glRectd(x,y,x+width,y+height);
}
public void update(int delta) {
updateXY();
draw();
}
public void updateXY(){
input();
//Updating target, velocity and position values
this.tx += this.dx;
this.ty += this.dy;
this.dx += this.ax;
this.dy += this.ay;
this.x += this.dx;
this.y += this.dy;
//Acceleration handling
if(tx > x){
this.ax += 1;
} else if(tx < x) {
this.ax -= 1;
} else {
this.ax = 0;
}
if(ty > y){
this.ay += 1;
} else if(ty < y) {
this.ay -= 1;
} else {
this.ay = 0;
}
}
public void input(){
//Event-Driven input
while(Keyboard.next()){
if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)){
if(ay == 0){
jump();
} else {
x = tx;
y = ty;
ay = 0;
}
}
}
//Polled input
if(Keyboard.isKeyDown(Keyboard.KEY_UP)){
move(DIR.UP);
} else {
stop(DIR.UP);
}
if(Keyboard.isKeyDown(Keyboard.KEY_DOWN)){
move(DIR.DOWN);
} else {
stop(DIR.DOWN);
}
if(Keyboard.isKeyDown(Keyboard.KEY_LEFT)){
move(DIR.LEFT);
} else {
stop(DIR.LEFT);
}
if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT)){
move(DIR.RIGHT);
} else {
stop(DIR.RIGHT);
}
}
public void jump(){
setAY(-10);
System.out.println("JUMP " + ay);
}
public void move(DIR d){
if(d == DIR.UP){
this.dy = -SPEED;
} else if(d == DIR.DOWN){
this.dy = SPEED;
} else if(d == DIR.LEFT){
this.dx = -SPEED;
} else{
this.dx = SPEED;
}
}
public void stop(DIR d){
if(d == DIR.UP || d == DIR.DOWN){
this.dy = 0;
} else {
this.dx = 0;
}
}
}
Public abstract class AbstractMoveableEntity extends AbstractEntity implements MoveableEntity {
protected double dx, dy, ax, ay;
public AbstractMoveableEntity(double x, double y, double width, double height) {
super(x, y, width, height);
this.dx = 0;
this.dy = 0;
this.ax = 0;
this.ay = 0;
}
public double getDX() {
return dx;
}
public double getDY() {
return dy;
}
public void setDX(double dx) {
this.dx = dx;
}
public void setDY(double dy) {
this.dy = dy;
}
public void setAX(double ax){
this.ax = ax;
}
public void setAY(double ay) {
this.ay = ay;
}
}
The problem is the part in the input() function marked //Polled input.
When the user presses the KEY_UP key, the first if-condition calls move(DIR.UP). At this point, dy is set to -SPEED. Then the next if-condition checks whether the user is pressing the KEY_DOWN key, sees that he isn't, and calls stop(DIR.DOWN). This sets dy to 0, effectively overwriting the previous call to move(DIR.UP).
The situation with LEFT/RIGHT is identical.
Related
I'm trying to make a doodle jump game and currently I cant find a way to make the still image change to leg image once it lands on the ground and then change back to still. It kind of does that for one side but not not for both. I've tried using nested if, but then it wouldn't detect the button press. Here's the code:
GameObject game;
PImage doodle;
void setup() {
size(640, 800);
smooth(4);
frameRate(10);
doodle = loadImage("https://i.imgur.com/ytwebph.png");
game = new Doodle(new PVector(width/2, height-doodle.height*2), doodle);
game.setWidthAndHeight(new PVector(width, height));
}
void draw() {
background(200);
game.display();
game.move();
}
void keyPressed() {
game.setMove(keyCode, true);
}
void keyReleased() {
game.setMove(keyCode, false);
}
protected class Doodle extends GameObject {
protected float velocityY, gravity, time;
protected float groundPosition;
protected int facing = 0; //0 = right; 1 = left
protected Doodle(PVector position, PImage picture) {
super(position, picture);
gravity = 20;
time = 0.4;
velocityY = 35*gravity*time;
super.setSpeed(10);
groundPosition = position.y - picture.height;
}
public void move() {
if (isRight || position.y < groundPosition) {
this.picture = doodleImg[0];
facing = 0;
} else if (isLeft || position.y < groundPosition) {
this.picture = doodleImg[2];
facing = 1;
}
position.x = position.x + speed*(int(isRight) - int(isLeft));
//border control
if (position.x+picture.width/2 <= 0) {
position.x = this.getWidthAndHeight().x-picture.width/2;
} else if (position.x+picture.width/2 >= this.getWidthAndHeight().x) {
position.x = 0-picture.width/2;
}
//jump
velocityY -= gravity * time;
position.y -= velocityY * time;
if (position.y > groundPosition) {
if (facing == 0) {
this.picture = doodleImg[1];
} else if (facing == 1) {
this.picture = doodleImg[3];
}
position.y = groundPosition;
velocityY = 35;
}
}
}
public class GameObject {
public PVector position, widthAndHeight;
public int size, speed;
public PImage picture;
public boolean isLeft, isRight;
public PImage[] doodleImg = new PImage[6];
public GameObject(PVector position, PImage picture) {
this.position = position;
this.picture = picture;
widthAndHeight = new PVector(0, 0);
speed = 1;
//0,1 right; 2,3 left; 4,5 shoot;
doodleImg[0] = loadImage("https://i.imgur.com/ytwebph.png");
doodleImg[1] = loadImage("https://i.imgur.com/Y0cFSFK.png");
doodleImg[2] = loadImage("https://i.imgur.com/FL3IhU5.png");
doodleImg[3] = loadImage("https://i.imgur.com/YuqWihj.png");
}
public void move() {
position.x = 0;
}
public void display() {
image(picture, position.x, position.y);
}
public boolean setMove(int keycode, boolean isPressed) {
switch(keycode) {
case LEFT:
return isLeft = isPressed;
case RIGHT:
return isRight = isPressed;
default:
return isPressed;
}
}
protected PVector getWidthAndHeight() {
return widthAndHeight;
}
void setSpeed(int speed) {
this.speed = speed;
}
public void setWidthAndHeight(PVector newWidthAndHeight) {
widthAndHeight = newWidthAndHeight;
}
}
First set the facing state, dependent on the isRight and isLeft:
if (isRight) {
facing = 0;
} else if (isLeft) {
facing = 1;
}
The set the image dependent on the state of facing and the vertical position position.y:
if (position.y < groundPosition) {
this.picture = doodleImg[facing==0 ? 0 : 2];
} else {
this.picture = doodleImg[facing==0 ? 1 : 3];
}
public void move() {
if (isRight) {
facing = 0;
} else if (isLeft) {
facing = 1;
}
if (position.y < groundPosition) {
this.picture = doodleImg[facing==0 ? 0 : 2];
} else {
this.picture = doodleImg[facing==0 ? 1 : 3];
}
position.x = position.x + speed*(int(isRight) - int(isLeft));
//border control
if (position.x+picture.width/2 <= 0) {
position.x = this.getWidthAndHeight().x-picture.width/2;
} else if (position.x+picture.width/2 >= this.getWidthAndHeight().x) {
position.x = 0-picture.width/2;
}
//jump
velocityY -= gravity * time;
position.y -= velocityY * time;
if (position.y > groundPosition) {
position.y = groundPosition;
velocityY = 35;
}
}
EDIT
: it seems that in my move() method, java has to skip one of the 2 if statements
Keeping it simple. I'm trying to make a GUI in java that models the following class Truck behavior: the blue squares are supposed to run up their diagonales, which they do. But when they are supposed to bounce back once they reach the edge point of the square they just fly away. I've placed a condition to prevent this, but it never passes. I'll upload GUI and Drawable, but I don't think they are needed.
Class Truck:
package construction_site;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.plaf.ButtonUI;
public class Truck extends Thread implements Drawable {
private boolean isFull = false;
private int x, y;
private int capacity;
private Panel panel;
static int r = 20;
private int dx, dy;
private Site site;
private Building building;
public Truck(int x, int y, Panel panel, Building building, Site site) {
this.x = x;
this.y = y;
this.building = building;
this.panel = panel;
this.site = site;
this.start();
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
#Override
public void run() {
super.run();
while (true) {
move();
panel.repaint();
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setDirection(int i) {
if (i == 0) {
dx = -1;
dy = -1;
}
if (i == 1) {
dx = 1;
dy = -1;
}
if (i == 2) {
dx = -1;
dy = 1;
}
if (i == 3) {
dx = 1;
dy = 1;
}
}
private void move() {
if (site.truckOnSite(x, y)) {
site.loadTruck(this);
dx *= -1;
dy *= -1;
}
if (building.containsTruck(this)) {
building.unloadTruck(this);
dx *= -1;
dy *= -1;
}
x += dx;
y += dy;
}
public int getDx() {
return dx;
}
public void setFull(boolean isFull) {
this.isFull = isFull;
}
#Override
public void draw(Graphics g) {
g.setColor(Color.BLUE);
if (isFull)
g.fillRect(x - 10, y - 10, r, r);
else
g.drawRect(x - 10, y - 10, r, r);
}
}
Class Panel:
package construction_site;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JPanel;
public class Panel extends JPanel {
private ArrayList<Drawable> drawables = new ArrayList<>();
private Site site;
private Building[] buildings = new Building[4];
private Truck[] trucks = new Truck[4];
private Van[] vans = new Van[4];
public Panel(int w, int h) {
setPreferredSize(new Dimension(w, h));
site = new Site(100, 75, 500, 500, this);
drawables.add(site);
buildings[0] = new Building(100, 75, this);
buildings[1] = new Building(100 + 500, 75, this);
buildings[2] = new Building(100, 75 + 500, this);
buildings[3] = new Building(100 + 500, 75 + 500, this);
for (Building b : buildings)
drawables.add(b);
trucks[0] = new Truck(100 + 250, 75 + 250, this, buildings[0], site);
trucks[1] = new Truck(100 + 250, 75 + 250, this, buildings[1], site);
trucks[2] = new Truck(100 + 250, 75 + 250, this, buildings[2], site);
trucks[3] = new Truck(100 + 250, 75 + 250, this, buildings[3], site);
for (int i = 0; i < 4; i++)
trucks[i].setDirection(i);
for (Truck t : trucks)
drawables.add(t);
}
#Override
public void paint(Graphics g) {
super.paint(g);
for (Drawable d : drawables)
d.draw(g);
g.setColor(Color.GREEN);
for (int i = 1; i <= 3; i++)
g.drawLine(buildings[0].getX(), buildings[0].getY(), buildings[i].getX(), buildings[i].getY());
g.drawLine(buildings[1].getX(), buildings[1].getY(), buildings[2].getX(), buildings[2].getY());
}
}
Class Building:
package construction_site;
import java.awt.Color;
import java.awt.Graphics;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Building extends Thread implements Drawable {
private Panel panel;
private boolean done = false;
private int x, y;
static int w = 100;
static int h = 100;
private ReentrantLock lock = new ReentrantLock();
private Condition insufficientMaterial = lock.newCondition();
private Condition insufficientMisc = lock.newCondition();
private Condition sufficient = lock.newCondition();
private int material = 0;
private int misc = 0;
private int spent = 0;
public Building(int x, int y, Panel panel) {
this.x = x;
this.y = y;
this.panel = panel;
this.start();
}
#Override
public void run() {
super.run();
lock.lock();
while(material < 100 )
try {
insufficientMaterial.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
spent += 150;
misc -= 50;
material -= 100;
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void unloadVan(Van v) {
lock.lock();
System.out.println("Truck got in");
if (material >= 100 && misc >=50) {
}
misc += 50;
v.setCapacity(0);
insufficientMisc.signalAll();
lock.unlock();
}
public void unloadTruck(Truck t) {
lock.lock();
material += 10000;
t.setCapacity(0);
t.setFull(false);
insufficientMaterial.signalAll();
lock.unlock();
}
public void setMaterial(int material) {
this.material = material;
}
public void setMisc(int misc) {
this.misc = misc;
}
public boolean containsVan(int x2, int y2) {
return ( Math.sqrt((x - x2)*(x - x2) + (y - y2)*(y - y2)) <= h/2 );
}
public boolean containsTruck(Truck t) {
return (x == t.getX() && y == t.getY());
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public void draw(Graphics g) {
g.setColor(Color.BLACK);
g.drawRect(x - 50, y - 50, 100, 100);
}
}
Class Site:
package construction_site;
import java.awt.Color;
import java.awt.Graphics;
public class Site implements Drawable {
private int x, y, w, h;
private Panel panel;
public Site(int x, int y, int w, int h, Panel panel) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.panel = panel;
}
public boolean contains(int x2, int y2) {
return (x == x2 && y == 2);
}
public boolean truckOnSite(int x2, int y2) {
return ( x2 == x + w / 2 && y2 == y + h / 2);
}
public boolean vanOnSite(int x2, int y2) {
return ( (x2 == x && y2 == y + h / 2) || (x2 == x + w && y2 == y + h / 2) );
}
public void loadVan(Van v) {
v.setCapacity(5000);
}
public void loadTruck(Truck t) {
t.setCapacity(10000);
t.setFull(true);
}
#Override
public void draw(Graphics g) {
g.setColor(Color.GRAY);
g.fillRect(x, y, w, h);
}
}
As it turned out much later, it doesn't seem truncation errors were the problem at hand. It was a mistake at setting the trucks' starting point and the condition that decides when they're supposed to turn the other way. What looked like the truck bouncing off, was actually the oppsoite truck from the same diagonal passing through. A simple change in direction of my Truck's move() method did the trick.
public void setDirection(int i) {
if (i == 0) {
dx = -1;
dy = -1;
}
if (i == 1) {
dx = 1;
dy = -1;
}
if (i == 2) {
dx = -1;
dy = 1;
}
if (i == 3) {
dx = 1;
dy = 1;
}
}
I'm a very new Programmer and am learning Java atm. I am writing a Langton's Ant, however I can't seem to get my ant to do what it's supposed to. The ant only seems to run up and down the grid and stays within column 10 and 11.
Here is the code:
package ameise;
public class Ant {
// Variables
// Position of the ant
int xPos;
int yPos;
// Which way is the ant facing
String direction;
Grid g;
boolean isFinished;
public Ant(int xPos, int yPos, String direction, Grid g) {
// Constructor
this.xPos = xPos;
this.yPos = yPos;
this.direction = direction;
this.g = g;
}
// Getter X Y Coordinates
public int getXPos() {
return xPos;
}
public int getYPos() {
return yPos;
}
// Setter X Y Coordinates
protected void setXPos(int xPos) {
this.xPos = xPos;
}
protected void setYPos(int yPos) {
this.yPos = yPos;
}
public String getDirection() {
return direction;
}
protected void setDirection(String direction) {
this.direction = direction;
}
public void run() {
while (xPos >= 0 && yPos >= 0 && xPos < g.getWidth() && yPos < g.getHeight()) {
System.out.println(xPos + "," + yPos + "," + "Facing " + direction + " Color " + g.isWhite(xPos, yPos));
if (xPos == 0) {
isFinished = true;
} else if (xPos == g.getWidth()) {
isFinished = true;
} else if (yPos == 0) {
isFinished = true;
} else if (yPos == g.getHeight()) {
isFinished = true;
}
// Determine Directions ...
if (direction.equals("NORTH")) {
if (g.isWhite(xPos, yPos)) {
g.setBlack(xPos, yPos);
setDirection("WEST");
} else {
g.setWhite(xPos, yPos);
setDirection("EAST");
}
yPos++;
} else if (direction.equals("WEST")) {
if (g.isWhite(xPos, yPos)) {
g.setBlack(xPos, yPos);
setDirection("SOUTH");
} else {
g.setWhite(xPos, yPos);
setDirection("NORTH");
}
xPos--;
} else if (direction.equals("SOUTH")) {
if (g.isWhite(xPos, yPos)) {
g.setBlack(xPos, yPos);
setDirection("EAST");
} else {
g.setWhite(xPos, yPos);
setDirection("WEST");
}
yPos--;
}
else if (direction.equals("EAST")) {
if (g.isWhite(xPos, yPos)) {
g.setBlack(xPos, yPos);
setDirection("NORTH");
} else {
g.setWhite(xPos, yPos);
setDirection("SOUTH");
}
xPos++;
}
}
}
}
*** CLASS GRID ***
package ameise;
public class Grid {
// Define the variables
boolean[][] grid;
int height;
int width;
// constructor with user parameters
public Grid(int height, int width) {
this.height = height;
this.width = width;
grid = new boolean[height][width];
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
grid[h][w] = true;
}
}
}
// Methods
// Getter and Setter for grid
public boolean[][] getGrid() {
return grid;
}
public void setGrid(boolean[][] grid) {
this.grid = grid;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public boolean isWhite(int h, int w) {
return grid[h][w];
}
protected void setWhite(int h, int w) {
if (h < height && w < width)
grid[h][w] = true;
}
protected void setBlack(int h, int w) {
if (h < height && w < width)
grid[h][w] = false;
}
public void printGrid() {
for (int h = 0; h < 19; h++) {
for (int w = 0; w < 19; w++) {
if (isWhite(h, w)) {
System.out.printf("S", grid[h][w]);
} else
System.out.printf("X", grid[h][w]);
}
System.out.println();
}
}
}
*** MAIN CLASS***
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
Grid grid = new Grid(20, 20);
Ant ant = new Ant(10, 10, "NORTH", grid);
ant.run();
grid.printGrid();
}
}
Somehow the ant only seems to be running. The output looks like
SSSSSSSSSSSSSSSSSSS
SSSSSSSSSSXXSSSSSSS
SSSSSSSSSSSSSSSSSSS
SSSSSSSSSSXXSSSSSSS
SSSSSSSSSSSSSSSSSSS
SSSSSSSSSSXXSSSSSSS
SSSSSSSSSSSSSSSSSSS
SSSSSSSSSSXXSSSSSSS
SSSSSSSSSSSSSSSSSSS
SSSSSSSSSSXXSSSSSSS
SSSSSSSSSSSSSSSSSSS
SSSSSSSSSSXXSSSSSSS
SSSSSSSSSSSSSSSSSSS
SSSSSSSSSSXXSSSSSSS
SSSSSSSSSSSSSSSSSSS
SSSSSSSSSSXXSSSSSSS
SSSSSSSSSSSSSSSSSSS
SSSSSSSSSSXXSSSSSSS
SSSSSSSSSSSSSSSSSSS
Langton's Ant moves into a cell and based on it's color decides which way it will turn to leave the current cell. Your code decides which way to turn but leaves in the direction it was already facing:
if (direction.equals("NORTH")) {
// This section decides which way ant will go based on the current cell
if (g.isWhite(xPos, yPos)) {
g.setBlack(xPos, yPos);
setDirection("WEST");
} else {
g.setWhite(xPos, yPos);
setDirection("EAST");
}
// This section move north, not in the direction the ant turns.
yPos++;
} //...
I think the best way to fix it is replace each case with something like:
if (direction.equals("NORTH")) {
if (g.isWhite(xPos, yPos)) {
g.setBlack(xPos, yPos);
setDirection("WEST");
xPos--; //move West
} else {
g.setWhite(xPos, yPos);
setDirection("EAST");
xPos++; //move East
}
} //...
I am creating an android app and I am creating a game and the droid has to be able to bounce off the walls and the edge of the screen. Here is my update method in my MainGamePanel.java file where I call the collision detection.
It works when it just has to bounce off the edge of the screen. However when I try to get it bounce off the wall objects it sometimes works. When it doesn't, it goes through the wall sometimes, although this only happens when it moves up and down. It also sometimes gets stuck in the wall. How would I modify the collision detection so I won't have these issues. Any help would be much appreciated.
public void update()
{
// check collision with right wall if heading right
if (droid.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT
&& droid.getX() + droid.getBitmap().getWidth() / 2 >= getWidth()) {
droid.getSpeed().toggleXDirection();
}
// check collision with left wall if heading left
else if (droid.getSpeed().getxDirection() == Speed.DIRECTION_LEFT
&& droid.getX() - droid.getBitmap().getWidth() / 2 <= 0) {
droid.getSpeed().toggleXDirection();
droid.getSpeed().setYv(0);
}
// check collision with bottom wall if heading down
else if (droid.getSpeed().getyDirection() == Speed.DIRECTION_DOWN
&& droid.getY() + droid.getBitmap().getHeight() / 2 >= getHeight()) {
droid.getSpeed().toggleYDirection();
droid.getSpeed().setXv(0);
}
// check collision with top wall if heading up
else if (droid.getSpeed().getyDirection() == Speed.DIRECTION_UP
&& droid.getY() - droid.getBitmap().getHeight() / 2 <= 0) {
droid.getSpeed().toggleYDirection();
droid.getSpeed().setXv(0);
}
for (int i = 0 ; i < listOfWs.length ; i++)
{
if (droid.getX() +(droid.getBitmap().getWidth()/2)+1 > listOfWs [i].giveLeft ()
&& droid.getX()-(droid.getBitmap().getWidth()/2)-1 < listOfWs [i].giveRight ()
&& droid.getY()+(droid.getBitmap().getHeight()/2)+1 > listOfWs [i].giveTop ()
&& droid.getY()-(droid.getBitmap().getHeight()/2)-1 < listOfWs [i].giveBottom () )
{
if(droid.getSpeed().getYv()==0){
droid.getSpeed().toggleXDirection();//Takes the speed and multiplies it by -1 so it changes direction
}
else{
droid.getSpeed().toggleYDirection();
}
}
}
// Update the lone droid
droid.update();
}
Here is my droid.java file that I used.
public class Droid {
private Bitmap bitmap; // the actual bitmap
private int x; // the X coordinate
private int y; // the Y coordinate
public Speed speed;
public Droid(Bitmap bitmap, int x, int y) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
speed= new Speed();
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, x - (bitmap.getWidth() /2), y - (bitmap.getHeight() / 2), null);
}
public void update() {
x += (int)(speed.getXv() * speed.getxDirection());
y += (int)(speed.getYv() * speed.getyDirection());
}
public Speed getSpeed(){
return speed;
}
}
This is the speed.java file.
public class Speed {
public static final int DIRECTION_RIGHT = 4;
public static final int DIRECTION_LEFT = -4;
public static final int DIRECTION_UP = -4;
public static final int DIRECTION_DOWN = 4;
private float xv = 1; // velocity value on the X axis
private float yv = 1; // velocity value on the Y axis
private int xDirection = DIRECTION_RIGHT;
private int yDirection = DIRECTION_DOWN;
public Speed() {
this.xv = 1;
this.yv = 1;
}
public Speed(float xv, float yv) {
this.xv = xv;
this.yv = yv;
}
public float getXv() {
return xv;
}
public void setXv(float xv) {
this.xv = xv;
}
public float getYv() {
return yv;
}
public void setYv(float yv) {
this.yv = yv;
}
public int getxDirection() {
return xDirection;
}
public void setxDirection(int xDirection) {
this.xDirection = xDirection;
}
public void setRight() {
xDirection = DIRECTION_RIGHT;
}
public void setLeft() {
xDirection = DIRECTION_LEFT;
}
public void setUp() {
yDirection = DIRECTION_UP;
}
public void setDown() {
yDirection = DIRECTION_DOWN;
}
public int getyDirection() {
return yDirection;
}
public void setyDirection(int yDirection) {
this.yDirection = yDirection;
}
// changes the direction on the X axis
public void toggleXDirection() {
xDirection = xDirection * -1;
}
// changes the direction on the Y axis
public void toggleYDirection() {
yDirection = yDirection * -1;
}
}
in the update method, in for circulation, it seems you make your logical operation there, would you make it more specific?
I'm working on my first 2D Java game using Swing, and I've run into an odd bug.
Here's the relevant code, first of all:
GamePanel.java
public class GamePanel extends JPanel implements KeyListener {
public GamePanel() {
setPreferredSize(new Dimension(STAGE_WIDTH, STAGE_HEIGHT));
Thread runner = new Thread(new Runnable() {
#Override
public void run() {
begin();
long lastUpdate = System.currentTimeMillis();
while (true) {
long elapsed = System.currentTimeMillis() - lastUpdate;
repaint();
if (elapsed < 16) {
try {
Thread.sleep(20 - elapsed);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
update((System.currentTimeMillis() - lastUpdate) / 1000.0);
lastUpdate = System.currentTimeMillis();
}
}
});
runner.start();
}
//variables
int bulletVelocity = 10;
final int STAGE_HEIGHT = 600;
final int STAGE_WIDTH = 800;
int playerWidth = 50;
int playerHeight = 50;
//lists
List<Bullet> bulletList = new ArrayList<>();
List<Enemy> enemyList = new ArrayList<>();
//objects
Player player = new Player((STAGE_WIDTH - playerWidth) / 2, (STAGE_HEIGHT - playerHeight) / 2, 0, 0, playerWidth, playerHeight);
public void begin() {
}
public void update(double delta) {
player.update(delta);
//System.out.println(delta);
for (Bullet bullet : bulletList) {
bullet.update();
}
for (Enemy enemy : enemyList) {
enemy.update(player.getXPos(), player.getYPos());
}
}
#Override
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.RED);
g.fillRect((int) player.getXPos(), (int) player.getYPos(), player.getWidth(), player.getHeight());
g.setColor(Color.BLUE);
for (Bullet bullet : bulletList) {
g.fillRect((int) bullet.getXPos(), (int) bullet.getYPos(), 10, 10);
}
g.setColor(Color.GREEN);
for (Enemy enemy : enemyList) {
g.fillOval((int) enemy.getXPos(), (int) enemy.getYPos(), enemy.getWidth(), enemy.getHeight());
}
}
#Override
public void keyTyped(KeyEvent e) {
}
private Set<Integer> keysDown = new HashSet<Integer>();
#Override
public void keyPressed(KeyEvent e) {
if (keysDown.contains(e.getKeyCode())) {
return;
}
keysDown.add(e.getKeyCode());
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
player.addAccelX(-1);
} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
player.addAccelX(1);
} else if (e.getKeyCode() == KeyEvent.VK_UP) {
player.addAccelY(-1);
} else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
player.addAccelY(1);
} else if (e.getKeyCode() == KeyEvent.VK_SPACE) {
Bullet bullet = new Bullet(player.getXPos() + (player.getWidth() / 2), player.getYPos(), bulletVelocity - (player.getYVel() / 4));
bulletList.add(bullet);
} else if (e.getKeyCode() == KeyEvent.VK_E) {
Enemy enemy = new Enemy(100, 100, Math.random() * 3 + .5, 10, 10);
enemyList.add(enemy);
} else if (e.getKeyCode() == KeyEvent.VK_A) {
System.out.println(toDegrees(atan2(player.getYPos() - 0, player.getXPos() - 0)));
}
}
#Override
public void keyReleased(KeyEvent e) {
keysDown.remove(e.getKeyCode());
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
player.addAccelX(1);
} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
player.addAccelX(-1);
} else if (e.getKeyCode() == KeyEvent.VK_UP) {
player.addAccelY(1);
} else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
player.addAccelY(-1);
}
}
}
Player.java
public class Player {
private final double MAX_VELOCITY = 500;
private final double ACCELERATION = 3000.0;
//friction is % ? Add that later
private final double FRICTION = 400.0;
private double mass = 10.0;
private double xPos = 400;
private double yPos = 200;
private double xVel = 0.0;
private double yVel = 0.0;
private int width = 100;
private int height = 100;
private int xDir = 0;
private int yDir = 0;
private boolean moving = false;
private double accelX = 0.0;
private double accelY = 0.0;
public Player() {
}
public Player(double xPos, double yPos, double xVel, double yVel, int width, int height) {
this.xPos = xPos;
this.yPos = yPos;
this.xVel = xVel;
this.yVel = yVel;
this.width = width;
this.height = height;
}
public void update(double delta) {
this.xVel += accelX * delta;
this.yVel += accelY * delta;
if(abs(xVel) > MAX_VELOCITY){xVel = MAX_VELOCITY * xDir;}
if(abs(yVel) > MAX_VELOCITY){yVel = MAX_VELOCITY * yDir;}
if(xVel > 0) xVel += -FRICTION / mass;
if(xVel < 0) xVel += FRICTION / mass;
//debugging
//System.out.println(yVel);
if(yVel > 0) yVel += -FRICTION / mass;
if(yVel < 0) yVel += FRICTION / mass;
//System.out.println(yVel);
//if(!moving){xVel = 0; yVel = 0;}
this.xPos += this.xVel * delta;
this.yPos += this.yVel * delta;
}
public void setMoving(boolean moving){
this.moving = moving;
}
public void move(double delta) {
/*
* Acceleration = Force / Mass
* Velocity += Acceleration * ElapsedTime (delta)
* Position += Velocity * ElapsedTime (delta)
*/
}
public double getAccel(){
return ACCELERATION;
}
public void addAccelX(int dir) {
this.accelX += ACCELERATION * dir;
//this.xDir = dir;
}
public void addAccelY(int dir) {
this.accelY += ACCELERATION * dir;
//this.yDir = dir;
}
public double getXPos() {
return this.xPos;
}
public double getYPos() {
return this.yPos;
}
public double getXVel() {
return this.xVel;
}
public double getYVel() {
return this.yVel;
}
public int getHeight() {
return this.height;
}
public int getWidth() {
return this.width;
}
public void addXPos(int delta) {
this.xPos += delta;
}
public void addYPos(int delta) {
this.yPos += delta;
}
public void addXVel(int delta) {
this.xVel += delta;
}
public void addYVel(int delta) {
this.yVel += delta;
}
}
(Please excuse the sloppy code.)
The little red square player moves fine, but when I release the arrow keys, the player moves (either down or to the right) with a velocity of 20 (arbitrary units at this point), which comes out to a few pixels/sec.
I think that it has something to do with the friction, but I'm not sure.
You never reset accelX and accelY and so the acceleration is continuously applied across frames. Your player should actually be accelerating, but I think that friction may be interacting in some way to create slow movement.