Having The "Camera" positioning On The Player in Java - java

So I've been having some trouble with positioning the "camera" on the player since this is my first time trying to accomplish this. Whenever I launch my game and I move my player, the camera doesn't seem to center on the player like I hope it to do and I don't know what is wrong with it. I've tried looking through online resources and checked out many questions on stack overflow but I could not find what I did wrong :/ . I am using Java and using the Slick2D engine. Here are my class files:
Camera.class:
private float offsetMaxX;
private float offsetMaxY;
private float offsetMinX = 0;
private float offsetMinY = 0;
public float camX;
public float camY;
public Camera () {
super ();
}
public void update (float playerX, float playerY, float mapX, float mapY){
offsetMaxX = mapX - Main.WIDTH;
offsetMaxY = mapY - Main.HEIGHT;
camX = playerX - Main.WIDTH/2;
camY = playerY - Main.HEIGHT/2;
if (camX > offsetMaxX) {
camX = offsetMaxX;
} else if (camX < offsetMinX) {
camX = offsetMinX;
}
if (camY > offsetMaxY) {
camY = offsetMaxY;
} else if (camY < offsetMinY) {
camY = offsetMinY;
}
}
public float getCamX() {
return camX;
}
public float getCamY() {
return camY;
}
public float getOffsetMaxX() {
return offsetMaxX;
}
public float getOffsetMaxY() {
return offsetMaxY;
}
public float getOffsetMinX() {
return offsetMinX;
}
public float getOffsetMinY() {
return offsetMinY;
}
public void setOffsetMaxX(float offsetMaxX) {
this.offsetMaxX = offsetMaxX;
}
public void setOffsetMaxY(float offsetMaxY) {
this.offsetMaxY = offsetMaxY;
}
public void setOffsetMinX(float offsetMinX) {
this.offsetMinX = offsetMinX;
}
public void setOffsetMinY(float offsetMinY) {
this.offsetMinY = offsetMinY;
}
And my Game.class:
// Player variables
public SpriteSheet playerSS = null;
protected InputHandler inputHandler;
public float playerX = Main.WIDTH/2, playerY = Main.HEIGHT/2;
private Animation sprite, runningAnimationLEFT, runningAnimationRIGHT, runningAnimationUP, runningAnimationDOWN;
private Animation standLEFT, standRIGHT, standUP, standDOWN; //THIS IS TO PREVENT ANIMATIONS FROM CONTINUING AFTER THE PLAYER STOPS
private int duration = 300;
public boolean isMoving, isLeft, isRight, isUp, isDown;
//Map
private Image testMap; //This is a test map
private float mapX = 1024, mapY = 1024;
//Camera
public Camera camera;
public Game (int stateID) {}
#Override
public int getID() {
return Main.game; //GAMESTATE = 1
}
#Override
public void init(GameContainer gameContainer, StateBasedGame stateBasedGame) throws SlickException {
playerSS = new SpriteSheet("res/characters/player_sprite_sheet.png", 50, 75);
testMap = new Image ("res/grassMap.png");
camera = new Camera();
// ANIMATIONS
runningAnimationDOWN = new Animation();
runningAnimationDOWN.setAutoUpdate(true);
runningAnimationDOWN.addFrame(playerSS.getSprite(1, 0), duration);
runningAnimationDOWN.addFrame(playerSS.getSprite(0, 0), duration);
runningAnimationDOWN.addFrame(playerSS.getSprite(2, 0), duration);
runningAnimationLEFT = new Animation();
runningAnimationLEFT.setAutoUpdate(true);
runningAnimationLEFT.addFrame(playerSS.getSprite(1, 1), duration);
runningAnimationLEFT.addFrame(playerSS.getSprite(0, 1), duration);
runningAnimationLEFT.addFrame(playerSS.getSprite(2, 1), duration);
runningAnimationRIGHT = new Animation();
runningAnimationRIGHT.setAutoUpdate(true);
runningAnimationRIGHT.addFrame(playerSS.getSprite(1, 2), duration);
runningAnimationRIGHT.addFrame(playerSS.getSprite(0, 2), duration);
runningAnimationRIGHT.addFrame(playerSS.getSprite(2, 2), duration);
runningAnimationUP = new Animation();
runningAnimationUP.setAutoUpdate(true);
runningAnimationUP.addFrame(playerSS.getSprite(1, 3), duration);
runningAnimationUP.addFrame(playerSS.getSprite(0, 3), duration);
runningAnimationUP.addFrame(playerSS.getSprite(2, 3), duration);
standDOWN = new Animation();
standDOWN.setAutoUpdate(true);
standDOWN.addFrame(playerSS.getSprite(1, 0), duration);
standLEFT = new Animation();
standLEFT.setAutoUpdate(true);
standLEFT.addFrame(playerSS.getSprite(1, 1), duration);
standRIGHT = new Animation();
standRIGHT.setAutoUpdate(true);
standRIGHT.addFrame(playerSS.getSprite(1, 2), duration);
standUP = new Animation();
standUP.setAutoUpdate(true);
standUP.addFrame(playerSS.getSprite(1, 3), duration);
sprite = standDOWN;
}
#Override
public void update(GameContainer gameContainer, StateBasedGame stateBasedGame, int delta) throws SlickException {
inputHandler.updateKeyboardRelay(gameContainer);
isMoving = false;
if (inputHandler.keyUP) {
isUp = true;
isDown = false;
isLeft = false;
isRight = false;
isMoving = true;
playerY -= delta * 0.1f;
} else if (inputHandler.keyDOWN) {
isDown = true;
isUp = false;
isLeft = false;
isRight = false;
isMoving = true;
playerY += delta * 0.1f;
} else if (inputHandler.keyLEFT) {
isLeft = true;
isUp = false;
isDown = false;
isRight = false;
isMoving = true;
playerX -= delta * 0.1f;
} else if (inputHandler.keyRIGHT) {
isRight = true;
isUp = false;
isDown = false;
isLeft = false;
isMoving = true;
playerX += delta * 0.1f;
}
if (isMoving) {
if (inputHandler.keyUP) {
sprite = runningAnimationUP;
sprite.update(delta);
} else if (inputHandler.keyDOWN) {
sprite = runningAnimationDOWN;
sprite.update(delta);
} else if (inputHandler.keyLEFT) {
sprite = runningAnimationLEFT;
sprite.update(delta);
} else if (inputHandler.keyRIGHT) {
sprite = runningAnimationRIGHT;
sprite.update(delta);
}
} else {
if (isDown) {
sprite = standDOWN;
sprite.update(delta);
} else if (isUp) {
sprite = standUP;
sprite.update(delta);
} else if (isLeft) {
sprite = standLEFT;
sprite.update(delta);
} else if (isRight) {
sprite = standRIGHT;
sprite.update(delta);
}
}
// Map Boundaries
if (playerX > mapX) {
playerX = mapX;
} else if (playerX < 0) {
playerX = 0;
}
if (playerY > mapY) {
playerY = mapY;
} else if (playerY < 0) {
playerY = 0;
}
camera.update(playerX, playerY, mapX, mapY);
}
#Override
public void render(GameContainer gameContainer, StateBasedGame stateBasedGame, Graphics graphics) throws SlickException {
testMap.draw(mapX - 1024, mapY - 1024);
graphics.translate(camera.getCamX(), camera.getCamY());
sprite.draw(playerX, playerY);
graphics.translate(-camera.getCamX(), -camera.getCamY());
graphics.drawString("Player X: " + playerX, 400, 400);
graphics.drawString("Player Y: " + playerY, 400, 415);
}
I feel like there is something specifically wrong in my Camera.class and my update(...) & render(...) methods, but I don't know what.

Here in your camera class in the update method try changing
camX = playerX - Main.WIDTH/2;
camY = playerY - Main.HEIGHT/2;
to
camX = playerX;
camY = playerY;
tell me if this does not work.

Related

Rectangle intersects not working while jumping

I am making a game with android. The player is a rectangle that has to jump over obstacles. When i jump i decrease the height and the y coordinates. When i run the game the rectangle is jumping but when i try to jump over an obstacle its still hitting it. So i think i forget to change a value but i have no idea what value. Sorry for my bad english and i am a beginner at coding.
This is my Player class:
package com.example.niek.speelveld;
import android.graphics.Canvas;
import android.graphics.Paint;
/**
* Created by Niek on 15-8-2017.
*/
public class Player extends GameObject {
private int score;
private boolean up;
private boolean playing;
private long startTime;
private int h = 0;
private boolean jump;
public Player(int x , int y){
super.x = x;
super.y = y;
width = 100;
height = GamePanel.HEIGHT;
score = 0;
startTime = System.nanoTime();
}
public void setUp(boolean b){up = b;}
public void update(){
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>100){
score++;
startTime = System.nanoTime();
}
if(up && h == 0){
jump = true;
up = false;
}
if (jump) {
if (h < 120) {
h = h + 7;
height = height - 7;
y = y - 7;
} else {
jump = false;
}
} else {
if (h > 0) {
h = h - 7;
height = height + 7;
y = y + 7;
}
}
}
public void draw(Canvas canvas){
Paint myPaint = new Paint();
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setStrokeWidth(7);
canvas.drawRect(x, y, width + x, height, myPaint );
myPaint.setStrokeWidth(1);
canvas.drawText("HIGHSCORE " + score, GamePanel.WIDTH - 100 , 0+myPaint.getTextSize(), myPaint);
}
public int getScore(){return score;}
public boolean getPlaying(){return playing;}
public void setPlaying(boolean b){playing = b;}
//public void resetScore(){score = 0;}
public boolean getJump() {
return jump;
}
}
And in my Gamepanel class i use these 2 methods. When i call the class obstacle.get(i).update(); its only updating the x value so its moving towards the player.
public void update(){
if(player.getPlaying()) {
bg.update();
player.update();
//Add obstacles with timer
long obstacleElapsed = (System.nanoTime()-obstacleStartTime)/1000000;
if(obstacleElapsed >(2000 - player.getScore()/4)){
obstacles.add(new Obstacle(BitmapFactory.decodeResource(getResources(), R.drawable.rsz_spike1), WIDTH + 10, HEIGHT - 51, 14, 51, player.getScore()));
//reset timer
obstacleStartTime = System.nanoTime();
}
}
//Loop through every obstacle and check collision
for(int i = 0; i<obstacles.size(); i++){
obstacles.get(i).update();
if (collision(obstacles.get(i), player)) {
obstacles.remove(i);
player.setPlaying(false);
Intent intent = new Intent(c, Result.class);
intent.putExtra("SCORE", player.getScore());
c.startActivity(intent);
break;
}
//Remove obstacles that are out of the screen
if (obstacles.get(i).getX() < -100) {
obstacles.remove(i);
break;
}
}
}
public boolean collision(GameObject o, GameObject p){
if(Rect.intersects(o.getRectangle(), p.getRectangle())){
return true;
}
return false;
}
#Override
public void draw(Canvas canvas){
//Get Width and Height from screen
final float scaleFactorX = (float)getWidth()/WIDTH;
final float scaleFactorY = (float)getHeight()/HEIGHT;
if(canvas!=null) {
final int savedState = canvas.save();
canvas.scale(scaleFactorX, scaleFactorY);
bg.draw(canvas);
player.draw(canvas);
//Draw obstacles
for(Obstacle o : obstacles ){
o.draw(canvas);
}
canvas.restoreToCount(savedState);
}
}
And finally the Player and the Obstacle class extends Gameobject where i have the getRectangle method.
public Rect getRectangle(){
return new Rect(x, y, x+width, y+height);
}

The onTouchEvent is not being called

I am making a game app that displays random circles all across the screen. This is all done in the onDraw method by making a never ending loop. However in the onTouchEvent method there is code that is called when a circle is clicked. The problem is when a circle is "touched" nothing happens, but sometimes something does(if you click it a lot before it disappears). Id like to know if there is a way to get the onTouch method working so these circles can be clicked.
public class DrawingView extends View{
public DrawingView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
RectF rectf = new RectF(0, 0, 200, 0);
private static final int w = 100;
public static int lastColor = Color.BLACK;
private final Random random = new Random();
private final Paint paint = new Paint();
private final int radius = 230;
private final Handler handler = new Handler();
public static int redColor = Color.RED;
public static int greenColor = Color.GREEN;
int randomWidth = 0;
int randomHeight = 0;
public static int addPoints = 0;
public static int savedScore;
public static List<String> a = new ArrayList<String>();
public static String[] savedScores = new String[a.size()];
Paint red;
public static int howManyPoints;
public static int highestScore = 0;
boolean isTouched;
Thread newThread = new Thread();
int t = 1;
int l = 0;
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
//handler.post(updateCircle);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
// handler.removeCallbacks(updateCircle);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// your other stuff here
Paint back = new Paint();
back.setColor(Color.BLACK);
Rect background = new Rect();
background.set(0, 0, canvas.getWidth(),canvas.getHeight() );
canvas.drawRect(background, back);
Paint newPaint = new Paint();
newPaint.setColor(Color.BLUE);
newPaint.setTextSize(60);
canvas.drawText("Beta v2", 10, 60, newPaint);
if(l < t){
lastColor = random.nextInt(2) == 1 ? redColor : greenColor;
paint.setColor(lastColor);
if(random == null){
randomWidth =(int) (random.nextInt(Math.abs(getWidth()-radius/2)) + radius/2f);
randomHeight = (random.nextInt((int)Math.abs((getHeight()-radius/2 + radius/2f))));
}else {
randomWidth =(int) (random.nextInt(Math.abs(getWidth()-radius/2)) + radius/2f);
randomHeight = (random.nextInt((int)Math.abs((getHeight()-radius/2 + radius/2f))));
}
canvas.drawCircle(randomWidth , randomHeight , radius , paint);
try {
newThread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
invalidate();
}
red = new Paint();
red.setColor(Color.BLUE);
red.setTextSize(150);
canvas.drawText("" + addPoints, 500, 1350, red);
}
#SuppressWarnings("deprecation")
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
int x = (int) event.getX();
int y = (int) event.getY();
if(isInsideCircle(x, y) == true){
if(lastColor == redColor){
howManyPoints = addPoints;
if(howManyPoints > highestScore){
highestScore = howManyPoints;
}
//handler.removeCallbacks(updateCircle);
lastColor = redColor;
addPoints = 0;
Intent i = new Intent(this.getContext(), YouFailed.class);
this.getContext().startActivity(i);
l = 1;
}
if(lastColor == greenColor){
addPoints++;
isTouched = true;
l = 0;
}
}else {
}
}
return false;
}
public boolean isInsideCircle(int x, int y){
if ((((x - randomWidth)*(x - randomWidth)) + ((y - randomHeight)*(y - randomHeight))) < ((radius)*(radius))){
return true;
}
return false;
}
}
You forgot to return true when you touch down
Try to add this
if(event.getAction() == MotionEvent.ACTION_DOWN){
//your code
return true;
}

Collision issue with Java Game

I am making a little Java Game for practice. Since changing up sprites and what not I am having problems with collision between Enemy and Projectiles. I will provide the Projectile class and can provide more if anyone would like to look! Help would much greatly be appreciated here as I've literally been trying to fix this for hours. Essentially each enemy should take 5 hits then disappear but I can't seem to get it like so. I think the problem lies within the bounds but I really have no idea at the minute what's up.
dn and dn2 are the enemy sprites. r is the projectile fired by my character
public class Projectile {
private int x, y, speedX;
private boolean visible;
private Rectangle r;
public Projectile(int startX, int startY) {
x = startX;
y = startY;
speedX = 7;
visible = true;
r = new Rectangle(0, 0, 0, 0);
}
public void update() {
x += speedX;
r.setBounds(x, y, 10, 5);
if (x > 800) {
visible = false;
r = null;
}
if (x < 800) {
checkCollision();
}
}
private void checkCollision() {
if (r.intersects(StartingClass.dn.r)) {
visible = false;
if (StartingClass.dn.health > 0) {
StartingClass.dn.health -= 1;
}
if (StartingClass.dn.health == 0) {
StartingClass.dn.setCenterX(-100);
StartingClass.score += 5;
}
}
if (r.intersects(StartingClass.dn2.r)) {
visible = false;
if (StartingClass.dn2.health > 0) {
StartingClass.dn2.health -= 1;
}
if (StartingClass.dn2.health == 0) {
StartingClass.dn2.setCenterX(-100);
StartingClass.score += 5;
}
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeedX() {
return speedX;
}
public boolean isVisible() {
return visible;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
}
public class Enemy {
private int power, centerX, speedX, centerY;
private Background bg = StartingClass.getBg1();
private Ninja ninja = StartingClass.getNinja();
public static boolean hit = false;
public Rectangle r = new Rectangle(0, 0, 0, 0);
public int health = 5;
private int movementSpeed;
// Behavioral Methods
public void update() {
follow();
centerX += speedX;
speedX = bg.getSpeedX() * 5 + movementSpeed;
r.setBounds(centerX - 25, centerY - 25, 50, 60);
if (r.intersects(Ninja.yellowRed)) {
checkCollision();
}
}
private void checkCollision() {
if (r.intersects(Ninja.rect) || r.intersects(Ninja.rect2) || r.intersects(Ninja.rect3) || r.intersects(Ninja.rect4)){
System.out.println("collision");
hit = true;
}
}
public void follow() {
if (centerX < -95 || centerX > 810) {
movementSpeed = 0;
}
else if (Math.abs(ninja.getCenterX() - centerX) < 5) {
movementSpeed = 0;
}
else {
if (ninja.getCenterX() >= centerX) {
movementSpeed = 1;
} else {
movementSpeed = -1;
}
}
}
public class Ninja {
// Constants are Here
final int JUMPSPEED = -20;
final int MOVESPEED = 5;
private int centerX = 100;
private int centerY = 377;
private boolean jumped = false;
private boolean movingLeft = false;
private boolean movingRight = false;
private boolean ducked = false;
private boolean readyToFire = true;
private int speedX = 0;
private int speedY = 0;
public static Rectangle rect = new Rectangle(0, 0, 0, 0);
public static Rectangle rect2 = new Rectangle(0, 0, 0, 0);
public static Rectangle rect3 = new Rectangle(0, 0, 0, 0);
public static Rectangle rect4 = new Rectangle(0, 0, 0, 0);
public static Rectangle yellowRed = new Rectangle(0, 0, 0, 0);
public static Rectangle footleft = new Rectangle(0, 0, 0, 0);
public static Rectangle footright = new Rectangle(0, 0, 0, 0);
private Background bg1 = StartingClass.getBg1();
private Background bg2 = StartingClass.getBg2();
public Rectangle r = new Rectangle(0, 0, 0, 0);
private ArrayList<Projectile> projectiles = new ArrayList<Projectile>();
public void update() {
// Moves Character or Scrolls Background accordingly.
if (speedX < 0) {
centerX += speedX;
}
if (speedX == 0 || speedX < 0) {
bg1.setSpeedX(0);
bg2.setSpeedX(0);
}
if (centerX <= 200 && speedX > 0) {
centerX += speedX;
}
if (speedX > 0 && centerX > 200) {
bg1.setSpeedX(-MOVESPEED / 5);
bg2.setSpeedX(-MOVESPEED / 5);
}
// Updates Y Position
centerY += speedY;
// Handles Jumping
speedY += 1;
if (speedY > 3) {
jumped = true;
}
// Prevents going beyond X coordinate of 0
if (centerX + speedX <= 60) {
centerX = 61;
}
rect.setRect(centerX - 34, centerY - 30, 67, 62);
rect2.setRect(rect.getX(), rect.getY() + 63, 68, 63);
rect3.setRect(rect.getX() - 26, rect.getY() + 32, 26, 20);
rect4.setRect(rect.getX() + 68, rect.getY() + 32, 26, 20);
yellowRed.setRect(centerX - 100, centerY - 110, 180, 180);
footleft.setRect(centerX - 50, centerY + 20, 50, 15);
footright.setRect(centerX, centerY + 20, 50, 15);
}
public void moveRight() {
if (ducked == false) {
speedX = MOVESPEED;
}
}
public void moveLeft() {
if (ducked == false) {
speedX = -MOVESPEED;
}
}
public void stopRight() {
setMovingRight(false);
stop();
}
public void stopLeft() {
setMovingLeft(false);
stop();
}
private void stop() {
if (isMovingRight() == false && isMovingLeft() == false) {
speedX = 0;
}
if (isMovingRight() == false && isMovingLeft() == true) {
moveLeft();
}
if (isMovingRight() == true && isMovingLeft() == false) {
moveRight();
}
}
public void jump() {
if (jumped == false) {
speedY = JUMPSPEED;
jumped = true;
}
}
public void shoot() {
if (readyToFire) {
Projectile p = new Projectile(centerX + 40, centerY + 80);
projectiles.add(p);
}
}
Problem solved . It lay within my enemy class in r.setBounds(). Just painted that rectangle to screen and adjusted coordinates and all was good

Libgdx - Random Color Change with Delay

So I'm having this issue with my game that I'm working on for practice and one of the things that I'm struggling with is having this random color change between these four colors red, green, blue, yellow. My objective is to have this ball bounce around the screen while changing between the four colors but I would like to have a delay or pause in between the swapping of the colors like for at least 3 or 5 seconds. So far in the code the ball seems to change but without delay I've tried using a few delay methods like Timer.Schedule but eveytime I use this the ball bounces around the screen but its all black and no color I would really appreciate any help? I felt silly asking a question like this because I have a feeling it may be a small issue.
public class Play implements Screen {
Game game;
private Rectangle field = new Rectangle();
private Ball ball = new Ball();
private Paddle paddle1 = new Paddle(), paddle2 = new Paddle();
private ShapeRenderer ballRenderer, paddleRenderer;
private float fieldTop, fieldBottom, fieldRight, fieldLeft;
private Color ballColor = new Color();
private Random rnd = new Random();
public Play(Game game){
this.game = game;
}
#Override
public void render(float delta) {
float dt = Gdx.graphics.getRawDeltaTime();
update(dt);
draw(dt);
}
private void update(float dt) {
updateBall(dt);
updatepaddle1(dt);
}
private void updatepaddle1(float dt) {
boolean moveLeft = false, moveRight = false;
if(Gdx.input.isTouched()){
moveLeft = true;
moveRight = false;
}
if(Gdx.input.isTouched()){
moveRight = true;
moveLeft = false;
}
if(moveRight){
paddle1.setVelocity(350f, 0f);
}else if(moveLeft){
paddle1.setVelocity(-350f, 0f);
}else{
paddle1.setVelocity(0, 0);
}
paddle1.Intergrate(dt);
}
private void updateBall(float dt) {
// TODO Auto-generated method stub
ball.Intergrate(dt);
ball.updateBounds();
if(ball.left() < fieldLeft){
ball.move(fieldLeft, ball.getY());
ball.reflect(true, false);
}
if(ball.right() > fieldRight){
ball.move(fieldRight - ball.getWidth(), ball.getVelocityX());
ball.reflect(true, false);
}
if(ball.bottom() < fieldBottom){
ball.move(ball.getX(), fieldBottom);
ball.reflect(false, true);
}
if(ball.top() > fieldTop){
ball.move(ball.getX(), fieldTop - ball.getHeight());
ball.reflect(false, true);
}
}
public void reset(){
ball.move(field.x + (field.width - ball.getWidth()) / 2, field.y + (field.height - ball.getHeight()) / 2);
Vector2 velocity = ball.getVelocity();
velocity.set(330f, 0f);
velocity.setAngle(360f-45f);
ball.setVelocity(velocity);
//set paddle
paddle1.move(field.x + (field.width * .4f), 0);
paddle2.move(field.x + (field.width * .4f), field.y + (field.height - paddle1.getHeight()));
}
private void draw(float dt) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
paddleRenderer.begin(ShapeType.Filled);
drawPaddles(dt);
paddleRenderer.end();
ballRenderer.begin(ShapeType.Filled);
ballColorSwap(ballColor);
drawBall(dt);
ballRenderer.end();
}
private void drawPaddles(float dt) {
paddleRenderer.rect(paddle1.getX(), paddle1.getY(), paddle1.getWidth(), paddle1.getHeight());
paddleRenderer.rect(paddle2.getX(), paddle2.getY(), paddle2.getWidth(), paddle2.getHeight());
}
int THRESHOLD = 4000;
long lastChanged = 0;
private void ballColorSwap(Color ballColor){
int rnd = (int)(Math.random() * 4);
if(rnd == 1){
ballColor.set(Color.RED);
}
if(rnd == 2){
ballColor.set(Color.BLUE);
}
if(rnd == 3){
ballColor.set(Color.GREEN);
}
if(rnd == 4){
ballColor.set(Color.YELLOW);
}
lastChanged = System.currentTimeMillis();
}
private void drawBall(float dt) {
if(System.currentTimeMillis() - lastChanged > THRESHOLD)
ballColorSwap(ballColor);
ballRenderer.circle(ball.getX(), ball.getY(), 20);
ballRenderer.setColor(ballColor);
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
field.set(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
fieldLeft = field.x;
fieldRight = field.x + field.width;
fieldBottom = field.y;
fieldTop = field.y + field.height;
paddleRenderer = new ShapeRenderer();
ballRenderer = new ShapeRenderer();
reset();
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
}
}
Can you just add one more variable to save a timestamp?
int THRESHOLD = 4000; // 4 seconds
long lastChanged = 0; // timestamp
public void ballColorSwap(){
// maybe call it here?
if(System.currentTimeMillis() - lastChanged < THRESHOLD)
return;
int rnd = (int)(Math.random() * 4);
if(rnd == 1){
ballColor.set(Color.RED);
}
if(rnd == 2){
ballColor.set(Color.BLUE);
}
if(rnd == 3){
ballColor.set(Color.GREEN);
}
if(rnd == 4){
ballColor.set(Color.YELLOW);
}
// set the timestamp
lastChanged = System.currentTimeMillis();
}
private void drawBall(float dt) {
ballRenderer.circle(ball.getX(), ball.getY(), 20);
ballRenderer.setColor(ballColor);
}
Note: I haven't tested this code. It might need some modification but hope you get the idea.

Getting NPE in 2D Game thread

I keep getting a NPE when I run this very basic 2D game. It has something to do with the Key Events but I am not sure how to fix this. Can someone help me? It says the NPE is on this line if (_input.up.isPressed()) {
Here is the InputHandler Class
public class InputHandler implements KeyListener {
public InputHandler(Game game) {
game.addKeyListener(this);
}
public class Key {
private boolean pressed = false;
public void toggle(boolean isPressed) {
pressed = isPressed;
}
public boolean isPressed() {
return pressed;
}
}
// public List<Key> keys = new ArrayList<Key>();
public Key up = new Key();
public Key down = new Key();
public Key left = new Key();
public Key right = new Key();
public void keyPressed(KeyEvent e) {
toggleKey(e.getKeyCode(), true);
}
public void keyReleased(KeyEvent e) {
toggleKey(e.getKeyCode(), false);
}
public void keyTyped(KeyEvent e) {
}
public void toggleKey(int keyCode, boolean isPressed) {
if (keyCode == KeyEvent.VK_W) {
up.toggle(isPressed);
} else if (keyCode == KeyEvent.VK_S) {
down.toggle(isPressed);
} else if (keyCode == KeyEvent.VK_A) {
left.toggle(isPressed);
} else if (keyCode == KeyEvent.VK_D) {
right.toggle(isPressed);
}
}
}
here is the Player Class
public class Player extends Mob {
private InputHandler _input;
private int _speed;
private int _r = 10;
private int _x, _y;
public Player(int x, int y, int speed, InputHandler input) {
super("Player", x, y, 1);
_input = input;
_speed = speed;
_x = x;
_y = y;
}
public boolean hasCollided(int dx, int dy) {
return false;
}
public void update() {
int dx = 0;
int dy = 0;
if (_input.up.isPressed()) {
dy--;
} else if (_input.down.isPressed()) {
dy++;
} else if (_input.left.isPressed()) {
dx--;
} else if (_input.right.isPressed()) {
dx++;
}
if (dx != 0 || dy != 0) {
move(dx, dy);
isMoving = true;
} else {
isMoving = false;
}
if (_x < _r)
_x = _r;
if (_y < _r)
_y = _r;
if (_x > Game.WIDTH - _r)
_x = Game.WIDTH - _r;
if (_y > Game.HEIGHT - _r)
_y = Game.HEIGHT - _r;
}
public void render(Graphics2D g) {
g.setColor(Color.BLACK);
g.fillOval(x - _r, y - _r, 2 * _r, 2 * _r);
g.setStroke(new BasicStroke(3));
g.setColor(Color.GRAY);
g.drawOval(x - _r, y - _r, 2 * _r, 2 * _r);
g.setStroke(new BasicStroke(1));
}
}
here is the game class which creates the player
public class Game extends Canvas implements Runnable {
private static Game _instance;
private static final String TITLE = "ProjectG";
public static final int WIDTH = 960;
public static final int HEIGHT = WIDTH * 3 / 4;
private static final int SCALE = 1;
// to make it have a higher resolution double the width and height but half
// the scale. You are doubling the width and height but keeping the same
// window size by reducing the scale
public static final Dimension SIZE = new Dimension(WIDTH * SCALE, HEIGHT * SCALE);
private static final int UPDATE_RATE = 60;
private static final int RENDER_RATE = 60;
private JFrame _frame;
private Thread _thread;
private boolean _running = false;
private int _tps = 0;
private int _fps = 0;
private int _totalTicks = 0;
private BufferedImage image;
private Graphics2D g;
public InputHandler input;
private Player player;
public Game() {
_instance = this;
setPreferredSize(SIZE);
setMinimumSize(SIZE);
setMaximumSize(SIZE);
_frame = new JFrame(TITLE);
_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
_frame.setLayout(new BorderLayout());
_frame.add(_instance, BorderLayout.CENTER);
_frame.pack();
_frame.setResizable(false);
_frame.setLocationRelativeTo(null);
_frame.setVisible(true);
player = new Player(Game.WIDTH / 2, Game.HEIGHT / 2, 1, input);
}
public synchronized void start() {
_running = true;
_thread = new Thread(this, TITLE + "_main");
_thread.start();
}
public synchronized void stop() {
_running = false;
if (_thread != null) {
try {
_thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void run() {
double lastUpdateTime = System.nanoTime();
double lastRenderTime = System.nanoTime();
final int ns = 1000000000;
final double nsPerUpdate = (double) ns / UPDATE_RATE;
final double nsPerRender = (double) ns / RENDER_RATE;
final int maxUpdatesBeforeRender = 1;
int lastSecond = (int) lastUpdateTime / ns;
int tickCount = 0;
int renderCount = 0;
image = new BufferedImage(WIDTH * SCALE, HEIGHT * SCALE, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
while (_running) {
long currTime = System.nanoTime();
int tps = 0;
while ((currTime - lastUpdateTime) > nsPerUpdate && tps < maxUpdatesBeforeRender) {
update();
tickCount++;
_totalTicks++;
tps++;
lastUpdateTime += nsPerUpdate;
}
if (currTime - lastUpdateTime > nsPerUpdate) {
lastUpdateTime = currTime - nsPerUpdate;
}
float interpolation = Math.min(1.0F, (float) ((currTime - lastUpdateTime) / nsPerUpdate));
render(interpolation);
draw();
renderCount++;
lastRenderTime = currTime;
int currSecond = (int) (lastUpdateTime / ns);
if (currSecond > lastSecond) {
_tps = tickCount;
_fps = renderCount;
tickCount = 0;
renderCount = 0;
lastSecond = currSecond;
System.out.println(_tps + " TPS " + _fps + " FPS");
}
while (currTime - lastRenderTime < nsPerRender && currTime - lastUpdateTime < nsPerUpdate) {
Thread.yield();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
currTime = System.nanoTime();
}
}
}
public void update() {
player.update();
}
public void render(float interpolation) {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
}
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH * SCALE, HEIGHT * SCALE);
g.setColor(Color.BLACK);
g.drawString("TPS: " + _fps + " FPS: " + _fps, 10, 20);
player.render(g);
}
public void draw() {
Graphics g2 = this.getGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
}
public Game getGame() {
return this;
}
}
You haven't initialized input, so what you pass to
player = new Player(Game.WIDTH / 2, Game.HEIGHT / 2, 1, input);
is null. You need to initialize it before
input = new InputHandler(this);

Categories