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;
}
}
Related
I am following this tutorial on how to create a Java2D platform game. I followed the code precisely, but when I tried to run it, the player moves way too fast when moving left and when jumping and falling compared to when it's moving right.
My player class looks like this:
package Entity;
import TileMap.*;
import java.awt.*;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
public class Player extends MapObject {
// Player stats
private int health, maxHealth, fire, maxFire, fireCost, fireBallDamage, scratchDamage, scratchRange;
private boolean dead, flinching, firing, scratching, gliding;
private long flinchTimer;
// private ArrayList<FireBall> fireballs;
private ArrayList<BufferedImage[]> sprites;
private final int[] numFrames = { 2, 8, 1, 2, 4, 2, 5 };
// Animation actions
private static final int IDLE = 0;
private static final int WALKING = 1;
private static final int JUMPING = 2;
private static final int FALLING = 3;
private static final int GLIDING = 4;
private static final int FIREBALL = 5;
private static final int SCRATCHING = 6;
private int currentAction;
// Constructor
public Player(TileMap tm) {
super(tm);
width = height = 30;
cWidth = cHeight = 20;
moveSpeed = 0.3;
maxSpeed = 1.6;
stopSpeed = 0.4;
fallSpeed = 0.15;
maxFallSpeed = 4.0;
jumpStart = -4.8;
stopJumpSpeed = 0.3;
facingRight = true;
health = maxHealth = 5;
fire = maxFire = 2500;
fireCost = 200;
fireBallDamage = 5;
//fireBalls = new ArrayList<FireBall>();
scratchDamage = 8;
scratchRange = 40;
// Load sprites
try {
BufferedImage spritesheet =
ImageIO.read( getClass().getResourceAsStream("/Sprites/Player/playersprites.gif"));
sprites = new ArrayList<BufferedImage[]>();
// Loop through animation actions
for (int i = 0; i < 7; i++){
BufferedImage[] bi = new BufferedImage[numFrames[i]];
for (int j = 0; j < numFrames[i]; j++) {
// numFrames[6] = SCRATCH has width = 60
if (i != 6) {
bi[j] = spritesheet.getSubimage(j * width, i * height, width, height);
} else {
bi[j] = spritesheet.getSubimage(j * width * 2, i * height, width, height);
}
}
sprites.add(bi); // Add BufferedImageArray to animations list
}
} catch (Exception e) { e.printStackTrace(); }
animation = new Animation();
currentAction = IDLE;
animation.setFrames(sprites.get(IDLE));
animation.setDelay(400);
}
// Getters
public int getHealth() { return health; }
public int getMaxHealth() { return maxHealth; }
public int getFire() { return fire; }
public int getMaxFire() { return maxFire; }
// Setters
public void setFiring() { firing = true; }
public void setScratching() { scratching = true; }
public void setGliding(boolean b) { gliding = b; }
private void getNextPosition() {
// Movement
if (left) {
dx -= moveSpeed;
if ( dx < -maxSpeed) { dx = 0; }
} else if (right) {
dx += moveSpeed;
if (dx > maxSpeed) { dx = maxSpeed; }
} else {
if (dx > 0) {
dx -= stopSpeed;
if ( dx < 0 ) { dx = 0; }
} else if (dx < 0) {
dx += stopSpeed;
if (dx > 0) { dx = 0; }
}
}
// Cannot attack while moving, unless in the air
if ( currentAction == SCRATCHING || currentAction == FIREBALL && !( jumping || falling)) { dx = 0; }
// Jumping
if (jumping && !falling) {
dy += jumpStart;
falling = true;
}
if (falling) {
if ( dy > 0 && gliding) { dy += fallSpeed * 0.1; }
else { dy += fallSpeed; }
if ( dy > 0 ) { jumping = false; }
if ( dy < 0 && !jumping ) { dy += maxFallSpeed; }
if ( dy > maxFallSpeed ) { dy = maxFallSpeed; }
}
}
public void update() {
// Update position
getNextPosition();
checkTileMapCollision();
setPosition(xtemp, ytemp);
// Set animations
if (scratching) {
if (currentAction != SCRATCHING) {
currentAction = SCRATCHING;
animation.setFrames(sprites.get(SCRATCHING));
animation.setDelay(50);
width = 60;
}
} else if (firing) {
if (currentAction != FIREBALL) {
currentAction = FIREBALL;
animation.setFrames(sprites.get(FIREBALL));
animation.setDelay(100);
width = 30;
}
} else if (dy > 0) {
if (gliding) {
if (currentAction != GLIDING) {
currentAction = GLIDING;
animation.setFrames(sprites.get(GLIDING));
animation.setDelay(100);
width = 30;
}
} else if (currentAction != FALLING) {
currentAction = FALLING;
animation.setFrames(sprites.get(FALLING));
animation.setDelay(100);
width = 30;
}
} else if (dy < 0) {
if ( currentAction != JUMPING) {
currentAction = JUMPING;
animation.setFrames(sprites.get(JUMPING));
animation.setDelay(-1);
width = 30;
}
} else if ( left || right ) {
if ( currentAction != WALKING) {
currentAction = WALKING;
animation.setFrames(sprites.get(WALKING));
animation.setDelay(40);
width = 30;
}
} else {
if ( currentAction != IDLE) {
currentAction = IDLE;
animation.setFrames(sprites.get(IDLE));
animation.setDelay(400);
width = 30;
}
}
animation.update();
// Set direction
if ( currentAction != SCRATCHING && currentAction != FIREBALL) {
if ( right) { facingRight = true; }
if ( left ) { facingRight = false; }
}
}
public void draw(Graphics2D g) {
setMapPosition();
// Draw player
if (flinching) {
long elapsed = (System.nanoTime() - flinchTimer) / 1000000;
if (elapsed / 100 % 2 == 0) { return; } // Gives the appearance of blinking
}
if (facingRight) {
g.drawImage(animation.getImage(), (int) (x + xmap - width/2), (int) (y + ymap - height/2), null);
} else {
g.drawImage(animation.getImage(), (int) (x + xmap - width/2 + width), (int) (y + ymap - height/2),
-width, height, null);
}
}
}
I tried changing
private void getNextPosition() {
// Movement
if (left) {
dx -= moveSpeed;
if ( dx < -maxSpeed) { dx = -maxSpeed; }
to
private void getNextPosition() {
// Movement
if (left) {
dx -= moveSpeed;
if ( dx < -maxSpeed) { dx = 0; }
Which helped for the left-movement, but it created a lag in the graphics, so I tried changing theAnimation-class which looks like this:
package Entity;
import java.awt.image.BufferedImage;
public class Animation {
private BufferedImage[] frames;
private int currentFrame;
private long startTime, delay;
private boolean playedOnce;
public void Animation() {
playedOnce = false;
}
public void setFrames(BufferedImage[] frames) {
this.frames = frames;
currentFrame = 0;
startTime = System.nanoTime();
playedOnce = false;
}
public void setDelay(long d) { delay = d; }
public void setFrame(int i) { currentFrame = i; }
public void update() {
if (delay == -1) { return; }
long elapsed = (System.nanoTime() - startTime) / 1000000;
if (elapsed > delay) {
currentFrame++;
startTime = System.nanoTime();
}
if (currentFrame == frames.length) {
currentFrame = 0;
playedOnce = true;
}
}
public int getFrame() { return currentFrame; }
public BufferedImage getImage() { return frames[currentFrame]; }
public boolean hasPlayedOnce() { return playedOnce; }
}
Which I thought was where I could fix the problem, but I am uncertain as I am new to gamelogic. Is there any way I can slow down the movement of the player? All help is appreciated!
I'm creating a 2D java game and ran into a nullpointer exception. Whenever I call my render in the playstate class, it throws the exception. I had previously rendered the Font file and got it to work when commenting out the player object references. The player "linkformatted.png" file is able to load after trying and catching, but the nullpointer exception stays. Changing the values didn't work.
public class PlayState extends GameState {
private Font font;
private Player player;
public PlayState(GameStateManager gsm) {
super(gsm);
font = new Font("font/ZeldaFont.png", 16, 16);
player = new Player(new Sprite("entity/linkformatted.png"), new Vector2f(100, 100), 32);
}
public void update() {
player.update();
}
public void input(MouseHandler mouse, KeyHandler key) {
player.input(mouse, key);
}
public void render(Graphics2D g) {
Sprite.drawArray(g, font, "YOU", new Vector2f(100, 100), 32, 32, 16, 0);
player.render(g);
}
}
public class Sprite {
private BufferedImage SPRITESHEET = null;
private BufferedImage[][] spriteArray;
private final int TILE_SIZE = 32;
public int w;
public int h;
private int wSprite;
private int hSprite;
public Sprite(String file) {
w = TILE_SIZE;
h = TILE_SIZE;
System.out.println("Loading: " + file + "...");
SPRITESHEET = loadSprite(file);
wSprite = SPRITESHEET.getWidth() / w;
hSprite = SPRITESHEET.getHeight() / h;
loadSpriteArray();
}
public Sprite(String file, int w, int h) {
this.w = w;
this.h = h;
System.out.println("Loading: " + file + "...");
SPRITESHEET = loadSprite(file);
wSprite = SPRITESHEET.getWidth() / w;
hSprite = SPRITESHEET.getHeight() / h;
loadSpriteArray();
}
public void setSize(int width, int height) {
setWidth(width);
setHeight(height);
}
public void setWidth(int i) {
w = i;
wSprite = SPRITESHEET.getWidth() / w;
}
public void setHeight(int i) {
h = i;
hSprite = SPRITESHEET.getHeight() / h;
}
public int getWidth() {
return w;
}
public int getHeight() {
return h;
}
private BufferedImage loadSprite(String file) {
BufferedImage sprite = null;
try {
sprite = ImageIO.read(getClass().getClassLoader().getResourceAsStream(file));
} catch(Exception e) {
System.out.println("Error: could not load file: " + file);
}
return sprite;
}
public void loadSpriteArray() {
spriteArray = new BufferedImage[wSprite][hSprite];
for(int x = 0; x < wSprite; x++) {
for(int y = 0; y < hSprite; y++) {
spriteArray[x][y] = getSprite(x, y);
}
}
}
public BufferedImage getSpriteSheet() {
return SPRITESHEET;
}
public BufferedImage getSprite(int x, int y) {
return SPRITESHEET.getSubimage(x * w, y * h, w, h);
}
public BufferedImage[] getSpriteArray(int i) {
return spriteArray[i];
}
public BufferedImage[][] getSpriteArray2(int i) {
return spriteArray;
}
public static void drawArray(Graphics2D g, ArrayList<BufferedImage> img, Vector2f pos, int width, int height, int xOffset, int yOffset) {
float x = pos.x;
float y = pos.y;
for(int i = 0; i < img.size(); i++) {
if(img.get(i) != null) {
g.drawImage(img.get(i), (int) x, (int) y, width, height, null);
}
x += xOffset;
y += yOffset;
}
}
public static void drawArray(Graphics2D g, Font f, String word, Vector2f pos, int width, int height, int xOffset, int yOffset) {
float x = pos.x;
float y = pos.y;
for(int i = 0; i < word.length(); i++ ) {
if(word.charAt(i) != 32); // the space
g.drawImage(f.getFont(word.charAt(i)), (int) x, (int) y, width, height, null);
x += xOffset;
y += yOffset;
}
}
}
public class Animation {
private BufferedImage[] frames;
private int currentFrame;
private int numFrames;
private int count;
private int delay;
private int timesPlayed;
public Animation(BufferedImage[] frames) {
timesPlayed = 0;
setFrames(frames);
}
public Animation() {
timesPlayed = 0;
}
public void setFrames(BufferedImage[] frames) {
frames = frames;
currentFrame = 0;
timesPlayed = 0;
delay = 2;
numFrames = frames.length;
}
public void setDelay(int i) { delay = i;}
public void setFrame(int i) { currentFrame = i;}
public void setNumFrames(int i) { numFrames = i;}
public void update() {
if(delay == -1) return;
count++;
if(count == delay) {
currentFrame++;
count = 0;
}
if(currentFrame == numFrames) {
currentFrame = 0;
timesPlayed++;
}
}
public int getDelay() {
return delay;
}
public int getFrame() {
return currentFrame;
}
public int getCount() {
return count;
}
public BufferedImage getImage() {
return frames[currentFrame];
}
public boolean hasPlayedOnce() {
return timesPlayed > 0;
}
public boolean hasPlayed(int i) {
return timesPlayed == i;
}
}
public class Player extends Entity {
public Player(Sprite sprite, Vector2f origin, int size) {
super(sprite, origin, size);
}
public void move() {
if(up) {
dy -= acc;
if(dy < -maxSpeed) {
dy = -maxSpeed;
}
} else {
if(dy < 0) {
dy += deacc;
if(dy > 0) {
dy = 0;
}
}
}
if(down) {
dy += acc;
if(dy < maxSpeed) {
dy = maxSpeed;
}
} else {
if(dy > 0) {
dy -= deacc;
if(dy < 0) {
dy = 0;
}
}
}
if(left) {
dx -= acc;
if(dx < -maxSpeed) {
dy = -maxSpeed;
}
} else {
if(dx < 0) {
dx += deacc;
if(dx > 0) {
dx = 0;
}
}
}
if(right) {
dx += acc;
if(dx > maxSpeed) {
dy = maxSpeed;
}
} else {
if(dx > 0) {
dx -= deacc;
if(dx < 0) {
dx = 0;
}
}
}
}
public void update() {
super.update();
move();
pos.x = dx;
pos.y = dy;
}
#Override
public void render(Graphics2D g) {
g.drawImage(ani.getImage(), (int) (pos.x), (int) (pos.y), size, size, null);
}
public void input(MouseHandler mouse, KeyHandler key) {
if(key.up.down) {
up = true;
} else {
up = false;
}
if(key.down.down) {
down = true;
} else {
down = false;
}
if(key.left.down) {
left = true;
} else {
left = false;
}
if(key.right.down) {
right = true;
} else {
right = false;
}
if(key.attack.down) {
attack = true;
} else {
attack = false;
}
}
}
Here is what is printed:
Loading: entity/linkformatted.png...
Exception in thread "GameThread" java.lang.NullPointerException
at com.zwellis.game.graphics.Animation.getImage(Animation.java:62)
at com.zwellis.game.entity.Player.render(Player.java:82)
at com.zwellis.game.states.PlayState.render(PlayState.java:34)
at com.zwellis.game.states.GameStateManager.render(GameStateManager.java:71)
at com.zwellis.game.GamePanel.render(GamePanel.java:133)
at com.zwellis.game.GamePanel.run(GamePanel.java:90)
at java.base/java.lang.Thread.run(Thread.java:834)
Here is what happens when I made another file to display the image:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ImageInFrame {
public static void main(String[] args) throws IOException {
String path = "entity/linkformatted.png";
File file = new File(path);
BufferedImage image = ImageIO.read(file);
JLabel label = new JLabel(new ImageIcon(image));
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(label);
f.pack();
f.setLocation(200,200);
f.setVisible(true);
}
}
Here is what happens:
Exception in thread "main" javax.imageio.IIOException: Can't read input file!
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1308)
at ImageInFrame.main(ImageInFrame.java:11)
Here is also the github link
https://github.com/xfyktcl/ZwellisKnight.git
I am trying to make a game. I want the projectiles (balls) that I shoot to each have their own individual collisions with objects and the margins of the game screen, but right now when one ball collides with the game screen margins, every balls' velocity.x or velocity.y is multiplied by -1 to simulate collision rather than just the individual ball that hit's velocity being modified. (When one ball hits, all balls' velocities are affected). The projectiles are stored in an ArrayList in the GameWorld class and are all given an identical velocity when they are shot. You pick a direction to shoot in, then balls are shot every 0.3s in that direction until all balls are shot.
Here is the code from my Projectiles class:
package com.trimble.gameobjects;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;
import com.trimble.gameworld.GameWorld;
public class Projectile {
private Vector2 velocity, acceleration;
private Vector2 position;
private final float RADIUS = 3f;
private boolean active, shot;
private GameWorld world;
private float theta;
public Projectile(float x, GameWorld world) {
this.world = world;
this.position = new Vector2();
this.position.x = x;
this.position.y = world.getGameRect().y - 3;
// hitbox = new Circle(position, 3f);
this.velocity = new Vector2();
this.acceleration = new Vector2(0, 0.5f);
this.active = false;
this.shot = false;
}
public void update(float delta) {
if (active) {
position.add(velocity.cpy().scl(delta));
velocity.add(acceleration.cpy().scl(delta));
// left
if (this.position.x <= 3) {
Gdx.app.log("hit", " left");
this.position.x = 3;
this.velocity.x *= -1;
}
// right
else if (this.position.x >= world.getGameRect().width - 3) {
Gdx.app.log("hit", " right");
this.position.x = world.getGameRect().width - 3;
this.velocity.x *= -1;
}
// top
if (this.position.y < world.getGameRect().y + world.getGameRect().height + 3) {
Gdx.app.log("hit", " top");
this.position.y = world.getGameRect().y + world.getGameRect().height + 3;
this.velocity.y *= -1;
}
// bottom
else if (this.position.y > world.getGameRect().y - 3 && velocity.y > 0) {
Gdx.app.log("hit", " bottom");
if (!this.world.hasTouched()) {
this.world.getBaseCircle().setPositionX(position.x);
this.world.setTouched(true);
}
zeroVelocity();
this.active = false;
this.position = world.getBaseCirclePos();
this.world.addInactive();
}
}
}
public Vector2 getVelocity() {
return velocity;
}
public float getVelocityX() {
return velocity.x;
}
public float getVelocityY() {
return velocity.y;
}
public void setVelocity(Vector2 velocity) {
this.velocity = velocity;
}
public void setVelocityX(float x) {
this.velocity.x = x;
}
public void setVelocityY(float y) {
this.velocity.y = y;
}
public float getTheta() {
return theta;
}
public void setTheta(float theta) {
this.theta = theta;
}
public void zeroVelocity() {
this.velocity.x = 0;
this.velocity.y = 0;
}
public Vector2 getPosition() {
return position;
}
public void setPositionY(float y) {
this.position.y = y;
}
public void setPositionX(float x) {
this.position.x = x;
}
public void setPosition(Vector2 position) {
this.position = position;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public float getR() {
return RADIUS;
}
public boolean wasShot() {
return shot;
}
public void setShot(boolean shot) {
this.shot = shot;
}
}
Here is the code in GameWorld which is called when the player shoots:
public void transitionHasShot() {
if (currentState == GameState.READY) {
currentState = GameState.HASSHOT;
velocity.y = (float) (-165 * Math.sin(theta));
velocity.x = (float) (165 * Math.cos(theta));
baseCircle.setActive(false);
for (Projectile p : projectiles) {
p.setVelocity(velocity);
}
projectiles.get(0).setActive(true);
}
}
Let me know if you need any more info.
I solved the problem by changing the code in transitionHasShot():
change
for (Projectile p : projectiles) {
p.setVelocity(velocity);
}
to:
for (Projectile p : projectiles) {
p.setVelocity(velocity.cpy());
}
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.