Remember playing Super Mario Bros.? When Mario moves, he runs, and then when the player stops moving, he stops, but he doesn't come to a complete stop. He slides a little bit. I need to accomplish that. Over the past 2 days, I've been completely rewriting the movement my Mario clone/platformer game, because the model I had before was inefficient and just crappy overall. Right now, I'm not sure how to continue that small bit of velocity so that the stop isn't so sudden. How would I accomplish this? All the code for movement below is in the Player class and the code for controls is in the Main class. So what can I do to detect when the player stops, and use that to add just a little bit of velocity?
Main:
import com.hasherr.platformer.entity.Player;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
public class Main {
private void display() {
try {
Display.setDisplayMode(new DisplayMode(1000, 550));
Display.setTitle("Unnamed Platformer Game");
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
System.exit(0);
}
// OpenGL
while (!Display.isCloseRequested()) {
Display.update();
Display.sync(60); // sync to 60 fps
initGL();
player.update();
handleKeyboardInput();
}
Display.destroy();
}
private boolean keyboardInUse() {
boolean keyboardInUse;
if (!(Keyboard.isKeyDown(Keyboard.KEY_A)
|| Keyboard.isKeyDown(Keyboard.KEY_D) || Keyboard
.isKeyDown(Keyboard.KEY_SPACE))) {
keyboardInUse = false;
} else {
keyboardInUse = true;
}
return keyboardInUse;
}
private void handleKeyboardInput() {
if (!keyboardInUse()) {
player.goingLeft = false;
player.goingRight = false;
player.resetVelocity();
}
if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
player.goingLeft = false;
player.goingRight = true;
player.moveRight();
} else if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
player.goingLeft = true;
player.goingRight = false;
player.moveLeft();
} else if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
player.jump();
}
}
private void initGL() {
// initial OpenGL items for 2D rendering
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(0, 1000, 0, 550, 1, -1);
// start rendering player image
player.grabTexture().bind();
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(player.xPos, player.yPos);
glTexCoord2f(1, 0);
glVertex2f(player.xPos + 150, player.yPos);
glTexCoord2f(1, 1);
glVertex2f(player.xPos + 150, player.yPos + 150);
glTexCoord2f(0, 1);
glVertex2f(player.xPos, player.yPos + 150);
glEnd(); // stop rendering this image
}
Player player = new Player();
public static void main(String[] args) {
Main main = new Main();
main.display();
}
}
Player:
import java.io.IOException;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;
public class Player {
public Texture playerTexture;
// Positions & speed
public float xPos = 20.0f; // This is initial
public float yPos = 0.0f; // Same as above.
public float xVel, yVel;
public static int gravityForce = 6;
public static int jumpVelocity = 100;
private float moveSpeed = 8.0f;
private static int MAX_MOVE_SPEED = 25;
public boolean isSupported = true; // Once again, initial value.
public boolean goingRight, goingLeft, canJump;
// movement methods & constants
public void update() {
applyGravity();
checkForSupport();
}
public Texture grabTexture() {
try {
playerTexture = TextureLoader.getTexture("PNG",
ResourceLoader.getResourceAsStream("res/test_char.png"));
} catch (IOException e) {
e.printStackTrace();
}
return playerTexture;
}
private void checkForSupport() {
if (yPos == 0) {
isSupported = true;
} else if (yPos > 0 /* and is not on a platform */) {
isSupported = false;
}
}
private void applyGravity() {
if (!isSupported) {
yPos -= gravityForce;
}
}
public void printPos(String moveMethod) {
System.out.println(" X: " + xPos + " Y: " + yPos + " Going Right: "
+ goingRight + " Going Left: " + goingLeft);
}
// movement methods
public void resetVelocity() {
moveSpeed = 15;
}
private void accelerateX() {
moveSpeed += (float) (moveSpeed * 0.0096);
if (moveSpeed >= MAX_MOVE_SPEED) {
moveSpeed = MAX_MOVE_SPEED;
}
System.out.println(moveSpeed);
}
private void accelerateY() {
}
public void moveRight() {
printPos("Moving Right!");
accelerateX();
xPos += moveSpeed;
}
public void moveLeft() {
printPos("Moving Left!");
accelerateX();
xPos -= moveSpeed;
}
public void jump() {
printPos("Jumping!");
accelerateY();
yPos += jumpVelocity;
}
}
Every update decrement Mario's velocity, and move mario's position by his velocity.
You should be allowing his velocity to persist across multiple updates. Currently you're only moving mario when a left or right arrow key is depressed. This is a fine approach, and works for some games, but now that you're wanting more physical behavior a new approach is necessary. Time to conserve some energy!
Try this instead:
float acceleration = 15;
private void accelerateX(float speed) {
moveSpeed += (float) (speed * 0.0096);
if (moveSpeed >= MAX_MOVE_SPEED) {
moveSpeed = MAX_MOVE_SPEED;
}else if(moveSpeed<=-MAX_MOVE_SPEED){ moveSpeed= - MAX_MOVE_SPEED;}
}
public void moveRight() {
printPos("Moving Right!");
accelerateX(acceleration);
}
public void moveLeft() {
printPos("Moving Left!");
accelerateX(-acceleration);
}
//call this every update.
public void update(){
float minMoveSpeed = 1;
//snap to zero movement if movespeed is too slow.
//this is so the player actually stops moving eventually. otherwise
//the dampening affect would constantly shift the player to and fro.
if(this.moveSpeed<minMoveSpeed && this.moveSpeed>-minMoveSpeed){
this.moveSpeed = 0;
}
else{
float dampening = 1f;
//Counter velocity. this will bring mario to a halt over a number of updates
//play with the value of dampening to get right effect.
double sign = -(int)Math.signum(moveSpeed);
float dampeningValue = dampening*sign;
this.moveSpeed += dampeningValue;
}
xPos+= this.moveSpeed;
}
This code allows his velocity to persist across updates and slowing brings Mario to a stop if velocity isn't being incremented/decremented by moveRight/moveLeft.
Also you should be scaling your velocity by time so the game runs similarly on different hardware. This is less important at this point in development; just keep it in mind for the future.
Related
This is my first post on stack overflow so I apologize in advance if I'm breaking any rules about posting, etc. I have been working on a an asteroids-esque shooting game and I can't figure out how to get the collision detection working between the rocks and the laser.
The source code can be found here. I had to make some changes to the update method of LevelScreen because the original code is dependent on using the BlueJ IDE. I found a fix in this post and got the collision working between the spaceship and the rocks.
The LevelScreen class
package com.mygdx.game;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import java.util.ArrayList;
public class LevelScreen extends BaseScreen {
private Spaceship spaceship;
private boolean gameOver;
private boolean rocksNeedRemoved;
private Rock toRemove;
private ArrayList<Rock> rocks;
private ArrayList<Laser> lasers;
public void initialize() {
gameOver = false;
toRemove = null;
rocksNeedRemoved = false;
BaseActor space = new BaseActor(0, 0, mainStage);
space.loadTexture("space.png");
space.setSize(800, 600);
BaseActor.setWorldBounds(space);
spaceship = new Spaceship(400, 300, mainStage);
rocks = new ArrayList<Rock>();
lasers = new ArrayList<Laser>();
rocks.add(new Rock(600, 500, mainStage));
rocks.add(new Rock(600, 300, mainStage));
rocks.add(new Rock(600, 100, mainStage));
rocks.add(new Rock(400, 100, mainStage));
rocks.add(new Rock(200, 100, mainStage));
rocks.add(new Rock(200, 300, mainStage));
rocks.add(new Rock(200, 500, mainStage));
rocks.add(new Rock(400, 500, mainStage));
lasers.add(new Laser(400, 500, mainStage));
}
public void update(float dt) {
//Code from book(Throws class not found error)
/*
for (BaseActor rockActor : BaseActor.getList(mainStage,
"Rock")) {
if (rockActor.overlaps(spaceship)) {
if (spaceship.shieldPower <= 0) {
Explosion boom = new Explosion(0, 0,
mainStage);
boom.centerAtActor(spaceship);
spaceship.remove();
spaceship.setPosition(-1000, -1000);
BaseActor messageLose = new BaseActor(0, 0,
uiStage);
messageLose.loadTexture("message-
lose.png");
messageLose.centerAtPosition(400, 300);
messageLose.setOpacity(0);
messageLose.addAction(Actions.fadeIn(1));
gameOver = true;
}
else {
spaceship.shieldPower -= 34;
Explosion boom = new Explosion(0, 0,
mainStage);
boom.centerAtActor(rockActor);
rockActor.remove();
}
}
for (BaseActor laserActor :
BaseActor.getList(mainStage, "Laser")) {
if (laserActor.overlaps(rockActor)) {
}
Explosion boom = new Explosion(0, 0,
mainStage);
boom.centerAtActor(rockActor);
laserActor.remove();
rockActor.remove();
}
}
if (!gameOver && BaseActor.count(mainStage, "Rock") ==
0) {
BaseActor messageWin = new BaseActor(0, 0,
uiStage);
messageWin.loadTexture("message-win.png");
messageWin.centerAtPosition(400, 300);
messageWin.setOpacity(0);
messageWin.addAction(Actions.fadeIn(1));
gameOver = true;
}
}
*/
// loop I used to get collision working between rocks
and spaceship
for (Rock each : rocks)
if (spaceship.overlaps(each) && !each.crashed &&
spaceship.shieldPower <= 0) {
Explosion boom = new Explosion(0, 0,
mainStage);
Explosion boom2 = new Explosion(0, 0,
mainStage);
boom.centerAtActor(spaceship);
boom2.centerAtActor(each);
spaceship.remove();
spaceship.setPosition(-1000, -1000);
each.crashed = true;
each.clearActions();
each.addAction(Actions.fadeOut(1));
each.addAction(Actions.after(Actions.removeActor()));
rocksNeedRemoved = true;
toRemove = each;
} else if (spaceship.overlaps(each) &&
!each.crashed) {
Explosion boom = new Explosion(0, 0,
mainStage);
boom.centerAtActor(each);
spaceship.shieldPower -= 34;
each.crashed = true;
each.clearActions();
each.addAction(Actions.fadeOut(1));
each.addAction(Actions.after(Actions.removeActor()));
rocksNeedRemoved = true;
toRemove = each;
}
//check for collision between rocks and lasers (Not
working correctly)
for (int i = rocks.size() - 1; i >= 0; i--) {
Rock rock = rocks.get(i);
for (int j = lasers.size() - 1; j >= 0; j--) {
Laser laser = lasers.get(j);
if(rock.getBounds().overlaps(laser.getBounds())) {
Explosion boom = new Explosion(0, 0,
mainStage);
boom.centerAtActor(rock);
rock.crashed = true;
rock.clearActions();
rock.addAction(Actions.fadeOut(1));
rock.addAction(Actions.after(Actions.removeActor()));
rocksNeedRemoved = true;
toRemove = rock;
}
}
}
}
//override default InputProcessor method
public boolean keyDown(int keycode) {
if (keycode == Keys.X)
spaceship.warp();
if (keycode == Keys.SPACE)
spaceship.shoot();
return false;
}
}
The Spaceship class.
package com.mygdx.game;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.math.MathUtils;
public class Spaceship extends BaseActor {
private Thrusters thrusters;
private Shield shield;
public int shieldPower;
public Spaceship(float x, float y, Stage s) {
super(x, y, s);
loadTexture("spaceship.png");
setBoundaryPolygon(8);
setAcceleration(100);
setMaxSpeed(100);
setDeceleration(10);
thrusters = new Thrusters(0, 0, s);
addActor(thrusters);
thrusters.setPosition(-thrusters.getWidth(),
getHeight() / 2 - thrusters.getHeight() / 2);
shield = new Shield(0, 0, s);
addActor(shield);
shield.centerAtPosition(getWidth() / 2, getHeight() /
2);
shieldPower = 100;
}
public void act(float dt) {
super.act(dt);
float degreesPerSecond = 160; //rotation speed
if (Gdx.input.isKeyPressed(Keys.LEFT))
rotateBy(degreesPerSecond * dt);
if (Gdx.input.isKeyPressed(Keys.RIGHT))
rotateBy(-degreesPerSecond * dt);
if (Gdx.input.isKeyPressed(Keys.UP)) {
accelerateAtAngle(getRotation());
thrusters.setVisible(true);
}
else {
thrusters.setVisible(false);
}
shield.setOpacity(shieldPower / 100f);
if (shieldPower <= 0)
shield.setVisible(false);
applyPhysics(dt);
wrapAroundWorld();
}
public void warp() {
if(getStage() == null)
return;
Warp warp1 = new Warp(0, 0, this.getStage());
warp1.centerAtActor(this);
setPosition(MathUtils.random(800),
MathUtils.random(600));
Warp warp2 = new Warp(0, 0, this.getStage());
warp2.centerAtActor(this);
}
public void shoot() {
if (getStage() == null)
return;
Laser laser = new Laser(0, 0, this.getStage());
laser.centerAtActor(this);
laser.setRotation(this.getRotation());
laser.setMotionAngle(this.getRotation());
}
}
The Laser class.
package com.mygdx.game;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.Action;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
public class Laser extends BaseActor {
Rectangle bounds;
public Laser(float x, float y, Stage s) {
super(x, y, s);
bounds = new Rectangle((int)getX(), (int)getY(),
(int)getWidth(), (int)getHeight());
loadTexture("laser.png");
addAction(Actions.delay(1));
addAction(Actions.after(Actions.fadeOut(0.5f)));
addAction(Actions.after(Actions.removeActor()));
setSpeed(400);
setMaxSpeed(400);
setDeceleration(0);
}
public void act(float dt) {
super.act(dt);
applyPhysics(dt);
wrapAroundWorld();
}
public Rectangle getBounds() {
return bounds;
}
private void setXY(float pX,float pY) {
setPosition(pX, pY);
bounds.setX((int)pX);
bounds.setY((int)pY);
}
}
The Rock class
package com.mygdx.game;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.Action;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.math.MathUtils;
import com.mygdx.game.BaseActor;
public class Rock extends BaseActor {
public boolean crashed;
Rectangle bounds;
public Rock(float x, float y, Stage s) {
super(x, y, s);
bounds = new Rectangle((int)getX(), (int)getY(),
(int)getWidth(), (int)getHeight());
loadTexture("rock.png");
float random = MathUtils.random(30);
addAction(Actions.forever(Actions.rotateBy(30 + random,
1)));
setSpeed(50 + random);
setMaxSpeed(50 + random);
setDeceleration(0);
setMotionAngle(MathUtils.random(360));
crashed = false;
}
public void act(float dt) {
super.act(dt);
applyPhysics(dt);
wrapAroundWorld();
}
public boolean isCrashed() {
return crashed;
}
public void crashed() {
crashed = true;
clearActions();
addAction(Actions.fadeOut(1));
addAction(Actions.after(Actions.removeActor()));
}
public Rectangle getBounds() {
return bounds;
}
private void setXY(float pX,float pY) {
setPosition(pX, pY);
bounds.setX((int)pX);
bounds.setY((int)pY);
}
}
Boundary and overlap methods from BaseActor class
public void setBoundaryPolygon(int numSides) {
float w = getWidth();
float h = getHeight();
float[] vertices = new float[2 * numSides];
for(int i = 0; i < numSides; i ++) {
float angle = i * 6.28f / numSides;
//x coordinate
vertices[2 * i] = w / 2 * MathUtils.cos(angle) + w / 2;
//y coordinate
vertices[2 * i + 1] = h / 2 * MathUtils.sin(angle) + h / 2;
}
boundaryPolygon = new Polygon(vertices);
}
public Polygon getBoundaryPolygon() {
boundaryPolygon.setPosition(getX(), getY());
boundaryPolygon.setOrigin(getOriginX(), getOriginY());
boundaryPolygon.setRotation(getRotation());
boundaryPolygon.setScale(getScaleX(), getScaleY());
return boundaryPolygon;
}
public boolean overlaps(BaseActor other) {
Polygon poly1 = this.getBoundaryPolygon();
Polygon poly2 = other.getBoundaryPolygon();
//initial text to improve performance
if(!poly1.getBoundingRectangle().overlaps(poly2.getBoundingRectangle()))
return false;
return Intersector.overlapConvexPolygons(poly1, poly2);
}
So I guess the real question would be how would I go about checking for collisions between the rocks ArrayList and the lasers fired by the player? At this point I just want to finish the game even if it's not using best practices. I tried using the method described here and received no errors but also no collision between lasers and rock. Even if I manually add a laser to the lasers ArrayList. This last post I found leads me to believe I need something like a getAllLasers() but I'm not 100% sure how to go about that. Would it be easier to just learn Box2D or Quadtree?
I realize this is a complex problem and want to thank you in advance for taking taking the time to read it. I'm happy to provide any more information you need.
You already have Rectangle bounds for both of this entities, this is all you need. You can use Rectangle.overlaps()
for(Laser laser: lasers){
for(Rock rock: rocks){
if(laser.getBounds().overlaps(rock.getBounds())){
//collided!
}
}
}
Make sure you are getting a updated rectangle/bounds. Add this extra line in both Rock and Laser getBounds() method:
public Rectangle getBounds() {
bounds.set(getX(),getY(),getWidth(),getHeight());
return bounds;
}
if your actors scales or rotate you should update bounds accordingly
I think problem may be with update your actors bounds, i can't find where you update it. I wrote similiar game and i change Bounds of actors on each update step and all works well in some lines...
public void update() {
...
// changing bounds
bounds = new Rectangle(position.x,position.y,
actorWidth,
actorHeight);
}
Or if you use other approach check that your bounds changing in time
I am attempting to embed a game into my website that I programmed in java. I have no idea how to take my code from eclipse(which is what my JDE is) and put it into my website. I am using a weebly.com website. I do have several unfinished classes, I want to upload my incomplete games as well as complete just to show progress. so I ask you, how do I get this code from eclipse, to my website. Thanks for the help and the following is my code.
This is my Main class:
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;
public class Main extends Applet implements Runnable {
private static final long serialVersionUID = 1L;
Thread th = new Thread(this);
boolean running = true;
public int Jweidth = 400, Jheight = 400;
Image dbImage;
Graphics dbGraphics;
Bullet b;
Player p;
Enemy e, e2, e3, e4, e5, e6, e7, e8;
HealthBar hb;
NameSign ns;
Restart r;
private boolean BFire;
public void init() {
//set window size
setSize(Jweidth, Jheight);
//calls player class
p = new Player(this);
//calls healthBar
hb = new HealthBar(this, p);
//calls enemy class
e = new Enemy(this);
e2 = new Enemy(42, 0, this);
e3 = new Enemy(84, 0, this);
e4 = new Enemy(126, 0, this);
e5 = new Enemy(0, 42, this);
e6 = new Enemy(42, 42, this);
e7 = new Enemy(84, 42, this);
e8 = new Enemy(126, 42, this);
//calls bullet class
b = new Bullet(this);
//calls nameSign class
ns = new NameSign(this);
//calls Restart class
r = new Restart(this);
}
public void start() {
//starts a new thread
th.start();
}
public void stop() {
running = false;
}
public void destroy() {
running = false;
}
public void run() {
while (running) {
setBFire(b.getFire());
//calls update method from player class
p.update(this);
//calls update method from enemy class
e.update(this, p);
e2.update(this, p);
e3.update(this, p);
e4.update(this, p);
e5.update(this, p);
e6.update(this, p);
e7.update(this, p);
e8.update(this, p);
//calls update method from fire class if BFire is true
if (setBFire(true)) {
b.update(this, p);
}
//calls update method from HealthBar class
hb.update(this, p);
//calls update method from NameSign class
ns.update(this);
//calls update method from Restart class
r.update(this, p);
repaint();
//sets Thread to repeat every 17 milliseconds
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//doublebuffer
public void update(Graphics g) {
dbImage = createImage(Jweidth, Jheight);
dbGraphics = dbImage.getGraphics();
paint(dbGraphics);
g.drawImage(dbImage, 0, 0, this);
}
//paint class
public void paint(Graphics g) {
//calls paint method from player class
p.paint(g, this);
//calls paint method from enemy class
e.paint(g, this);
e2.paint(g, this);
e3.paint(g, this);
e4.paint(g, this);
e5.paint(g, this);
e6.paint(g, this);
e7.paint(g, this);
e8.paint(g, this);
//calls paint method from bullet class
b.paint(g, this);
//calls paint method from healthBar class
hb.paint(g, this);
//calls paint method from nameSign class
ns.paint(g, this);
//calls paint method from Restart class
r.paint(g);
}
public int getJweidth() {
return Jweidth;
}
public int getJheight() {
return Jheight;
}
//ignore all boolean Bfire methods
public boolean isBFire() {
return BFire;
}
public boolean setBFire(boolean bFire) {
BFire = bFire;
return bFire;
}
}
This is my Enemy class:
import java.awt.*;
import java.net.URL;
public class Enemy {
//Enemy ints
private int x = 0, y = 0, speed = 2;
private URL url;
private Image Enemy;
//adds image
public Enemy(Main m){
url = m.getDocumentBase();
Enemy = m.getImage(url, "Enemy.png");
}
public Enemy(int i, int j, Main m) {
url = m.getDocumentBase();
Enemy = m.getImage(url, "Enemy.png");
x = i;
y = j;
}
//same as run method but just for the enemy
public void update(Main m, Player p){
x += speed;
if(x <= 0){
speed = 2;
y += 32;
}
else if(x > m.getJweidth() - 32){
speed = -2;
y += 32;
}
//calls collision method
collision(p);
}
//enemy player hitbox
private void collision(Player p) {
int Px = p.getX();
int Py = p.getY();
int Pr = p.getRadious();
if(Px - Pr <= x && Px + Pr >= x && Py - Pr <= y && Py + Pr >= y){
p.hit();
}
}
//Graphics for enemy
public void paint(Graphics g, Main m){
g.drawImage(Enemy, x, y, m);
}
}
This is my Bullet class (this game is a work in progress and this class isn't working, but that is just unfinished work that I will do soon)
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.net.URL;
public class Enemy {
//Enemy ints
private int x = 0, y = 0, speed = 2;
private URL url;
private Image Enemy;
//adds image
public Enemy(Main m) {
url = m.getDocumentBase();
Enemy = m.getImage(url, "Enemy.png");
}
public Enemy(int i, int j, Main m) {
url = m.getDocumentBase();
Enemy = m.getImage(url, "Enemy.png");
x = i;
y = j;
}
//same as run method but just for the enemy
public void update(Main m, Player p) {
x += speed;
if (x <= 0) {
speed = 2;
y += 32;
} else if (x > m.getJweidth() - 32) {
speed = -2;
y += 32;
}
//calls collision method
collision(p);
}
//enemy player hitbox
private void collision(Player p) {
int Px = p.getX();
int Py = p.getY();
int Pr = p.getRadious();
if (Px - Pr <= x && Px + Pr >= x && Py - Pr <= y && Py + Pr >= y) {
p.hit();
}
}
//Graphics for enemy
public void paint(Graphics g, Main m) {
g.drawImage(Enemy, x, y, m);
}
}
This is my Restart class(once again unfinished but on the way)
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Restart implements KeyListener {
private int x, y;
private int pHealth;
private String string = "Would you like to play again?";
private boolean restart = false;
public Restart(Main m) {
x = 600;
y = 600;
}
public void update(Main m, Player p) {
//checks if players health = 0 and if restart is true
pHealth = p.getpHealth();
if (setRestart(true && pHealth <= 0)) {
System.out.println("Restart");
x = m.Jweidth / 2 - 75;
y = m.Jheight / 2;
}
//reset ints for player
//TODO
//reset ints for enemy
//TODO
//reset ints for bullet
//TODO
//reset ints for healthbar
//TODO
}
public void paint(Graphics g) {
g.drawString(string, x, y);
}
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_F1: {
setRestart(true);
break;
}
}
}
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_F1: {
setRestart(false);
break;
}
}
}
public void keyTyped(KeyEvent arg0) {
}
//ignore all boolean methods
public boolean isRestart() {
return restart;
}
public boolean setRestart(boolean restart) {
this.restart = restart;
return restart;
}
}
You will have to use Applets to embed your Java program in a browser, or Java Web Start if you just want to start it from the web in a new window.
Some security issues may apply depending on the Java version you are using.
Here are some examples on how to do it:
https://docs.oracle.com/javase/tutorial/deployment/applet/
http://www.javatpoint.com/java-applet
And here for the Java Web Start:
https://docs.oracle.com/javase/tutorial/deployment/webstart/
You're gonna need to make a .jar file and a compiled .class file, no .java file. To implement Java code in HTML, you can use the deprecated <applet> tag, or the new <object> tag.
<object codetype="application/java" classid="java:yourclass.class" archive="yourjar.jar" width="1000" height="1000"></object>
codetype="application/java" - The type of code, use application/java.
classid="?" - Java class to run, eg. java:MyApplet.class
archive="url" - Address or filename of the Java archive file (.jar) containing the class files.
width="?" - The width of the window, in pixels.
height="?" - The height of the window, in pixels.
Just telling you, I'm not sure that it'll work.
I'm using the Java AWT class to make a wall made up of rectangles on both sides. The wall class extends rectangles, and uses the same variables to draw to the screen.
Walls Class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
public class Walls extends Rectangle {
public Walls(int startX, int startY, int width, int height ){
//super(startX, startY, width, height);
//
//Checking with this way for the collision detection
this.x = startX;
this.y = startY;
this.width = width;
this.height = height;
//this.wallStartX = startX;
//this.wallStartY = startY;
//this.wallWidth = width;
//this.wallHeight = height;
}
public void draw(Graphics g){
g.setColor(Color.GRAY);
//g.fillRect( this.wallStartX, this.wallStartY, this.wallWidth, this.wallHeight);
//Trying with the rectangle methods
g.fillRect( this.x, this.y, this.width, this.height);
}
I used the rectangle.intersects method to check for collision prediction. It works with the left wall, but it seems to collide with the right wall all the time, even when the player square is not touching. I've used the same code for the left and right wall, and I made sure that the arguments for the wall are the same for the rectangle in the class above.
Based on Worms game from Killer Code Programming in Java
RacerPanel:
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.text.DecimalFormat;
import java.util.Random;
import java.awt.event.KeyEvent; //Should be for Key Usage
import java.awt.event.KeyListener;
public class RacingPanel extends GamePanel implements KeyListener {
///KeyListener from https://www.youtube.com/watch?v=5UaEUrbpDPE
//Q: Serial ID? http://stackoverflow.com/questions/285793/what-is-a- serialversionuid-and-why-should-i-use-it
private static final long serialVersionUID = 1825086766957972644L;
private DecimalFormat df = new DecimalFormat("0.##"); // 2 dp
private Main_Racer mrTop;
private Racer bob;
private Walls josephine;
private Walls jeremy;
private static Random randomGenerator = new Random();
boolean wallBuilder;
int leftCreateorDestroy = 100;
int rightCreateorDestroy = 100;
//private ArrayList()[] Walls kinderland;
//Q
private Font font;
private FontMetrics metrics;
//Q: definitely find out what this method is doing
public RacingPanel( Main_Racer rc, long period) {
super(period);
mrTop = rc;
this.addKeyListener(this);
}
//In case we want to integrate mice
//Q: Why void? Why protected?
protected void mousePress( int x, int y){
}
//Q: in the worm game, it calls
//fred.move(), presumably to move the worm
//wcTop.setTimeSpent(timeSpentInGame);
//Probably a counter
protected void simpleUpdate(){
}
//Q: Assuming that this should be things the
//game starts off with, like the block,
//the course. Also, font
protected void simpleInitialize(){
//T: Maybe I need to initialize the racer
bob = new Racer(PWIDTH, PHEIGHT);
josephine = new Walls(0, 35, 100, 1);
jeremy = new Walls(PWIDTH-100, 35, 100,1);
//That did it!
// so the arguments to the racer update change
//where the square was rendered
//TJ: I need to loop in such a way that will draw random variables
// set up message font
font = new Font("SansSerif", Font.BOLD, 24);
metrics = this.getFontMetrics(font);
}
protected void simpleRender(Graphics dbg) {
if(!gameOver){
//These two seem pretty straight forward
dbg.setColor(Color.blue);
dbg.setFont(font);
// report frame count & average FPS and UPS at top left
// dbg.drawString("Frame Count " + frameCount, 10, 25);
dbg.drawString("Average FPS/UPS: " + df.format(averageFPS) + ", "
+ df.format(averageUPS), 20, 25); // was (10,55)
dbg.setColor(Color.black);
// draw game elements: the obstacles and the worm
//This'll probably be the block and the
//course instead
//obs.draw(dbg);
//fred.draw(dbg);
bob.draw(dbg);
//jeremy.draw(dbg);
//See if we can draw this thing over and over
for(int i = 35; i < PHEIGHT; i++){
wallBuilder = randomGenerator.nextBoolean();
if(wallBuilder == false){
if ( leftCreateorDestroy < PWIDTH/2 - 50)
leftCreateorDestroy++;
}
else{
if(leftCreateorDestroy > 0){
leftCreateorDestroy--;
}
}
josephine = new Walls(0, i, leftCreateorDestroy, 1);
josephine.draw(dbg);
wallBuilder = randomGenerator.nextBoolean();
//This wall keeps colliding with the other wall
//Also, it isn't set to the other side of the screen due to conventions
if(wallBuilder == false){
//if ( (PWIDTH - rightCreateorDestroy) > (PWIDTH/2-150))
if ( rightCreateorDestroy > 0)
rightCreateorDestroy--;
}
else{
if((PWIDTH/2 + 50) < PWIDTH - rightCreateorDestroy){
rightCreateorDestroy++;
}
}
//PWIDTH - rightCreateorDestroy is the length of the
jeremy = new Walls((PWIDTH - rightCreateorDestroy), i, rightCreateorDestroy, 1);
//jeremy = new Walls((PWIDTH - rightCreateorDestroy), i, 100, 1);
//Let's see if it will draw negative; will not;
jeremy.draw(dbg);
//Now to put up collision detection
if(bob.intersects(josephine) ){
System.out.println("Ouch!");
gameOver = true;
}
//System.out.println(bob.);
else if( bob.intersects(jeremy) ){
Rectangle Sektor = bob.intersection(jeremy);
System.out.println(Sektor);
System.out.println(jeremy);
}
//System.out.println("Yow!");
//Problems seem to be with the right side; let's take out the right and check.
//For some reason, intersecting all of the time.
}
}
//1msecond is too long. Starts clipping;
/* try{
Thread.sleep(1000);
}catch ( InterruptedException exc ){
System.out.println("No work");
} */
}
//So this does draw over and over again
//FPS/UPS Still good
//Pretty straight forward as well. Just need
//to see when it is called
protected void gameOverMessage(Graphics g)
// center the game-over message in the panel
{
//Keeps updating after death...
String msg = "Game Over. Your Score: " + timeSpentInGame;
int x = (PWIDTH - metrics.stringWidth(msg)) / 2;
int y = (PHEIGHT - metrics.getHeight()) / 2;
g.setColor(Color.red);
g.setFont(font);
g.drawString(msg, x, y);
} // end of gameOverMessage()
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT){
//System.out.println("Right");
//Should set x position to current position plus 1
bob.setRacerPositionX(bob.getRacerPositionX() + 1);
}
if (e.getKeyCode() == KeyEvent.VK_LEFT){
// System.out.println("Left");
bob.setRacerPositionX(bob.getRacerPositionX() - 1);
}
if (e.getKeyCode() == KeyEvent.VK_UP){
//System.out.println("Up");
bob.setRacerPositionY(bob.getRacerPositionY() - 1);
}
if (e.getKeyCode() == KeyEvent.VK_DOWN){
//System.out.println("Down");
bob.setRacerPositionY(bob.getRacerPositionY() + 1);
}
}
Game Panel Class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DecimalFormat;
import javax.swing.JPanel;
public abstract class GamePanel extends JPanel implements Runnable {
private static final long serialVersionUID = 1863596360846514344L;
private static long MAX_STATS_INTERVAL = 1000000000L;
// private static long MAX_STATS_INTERVAL = 1000L;
// record stats every 1 second (roughly)
private static int NUM_FPS = 10;
// number of FPS values stored to get an average
protected static final int PWIDTH = 500; // size of panel
protected static final int PHEIGHT = 400;
protected static final int NO_DELAYS_PER_YIELD = 16;
/*
* Number of frames with a delay of 0 ms before the animation thread yields
* to other running threads.
*/
protected static int MAX_FRAME_SKIPS = 5; // was 2;
// no. of frames that can be skipped in any one animation loop
// i.e the games state is updated but not rendered
private Thread animator; // the thread that performs the animation
protected boolean running = false; // used to stop the animation thread
protected boolean isPaused = false;
protected long period; // period between drawing in _nanosecs_
// used for gathering statistics
private long statsInterval = 0L; // in ns
private long prevStatsTime;
private long totalElapsedTime = 0L;
private long gameStartTime;
protected int timeSpentInGame = 0; // in seconds
private long frameCount = 0;
private double fpsStore[];
private long statsCount = 0;
protected double averageFPS = 0.0;
private long framesSkipped = 0L;
private long totalFramesSkipped = 0L;
private double upsStore[];
protected double averageUPS = 0.0;
private DecimalFormat df = new DecimalFormat("0.##"); // 2 dp
// used at game termination
protected boolean gameOver = false;
// off screen rendering
private Graphics dbg;
private Image dbImage = null;
public GamePanel(long period) {
this.period = period;
setBackground(Color.white);
setPreferredSize(new Dimension(PWIDTH, PHEIGHT));
setFocusable(true);
requestFocus(); // the JPanel now has focus, so receives key events
readyForTermination();
simpleInitialize();
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
mousePress(e.getX(), e.getY());
}
});
// initialise timing elements
fpsStore = new double[NUM_FPS];
upsStore = new double[NUM_FPS];
for (int i = 0; i < NUM_FPS; i++) {
fpsStore[i] = 0.0;
upsStore[i] = 0.0;
}
} // end of GamePanel()
/**
* Sets up a listener to kill the game loop if the user attempts to quit
*/
private void readyForTermination() {
addKeyListener(new KeyAdapter() {
// listen for esc, q, end, ctrl-c on the canvas to
// allow a convenient exit from the full screen configuration
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if ((keyCode == KeyEvent.VK_ESCAPE)
|| (keyCode == KeyEvent.VK_Q)
|| (keyCode == KeyEvent.VK_END)
|| ((keyCode == KeyEvent.VK_C) && e.isControlDown())) {
running = false;
}
}
});
} // end of readyForTermination()
/**
* Triggers the animation loop to start
*/
public void addNotify()
// wait for the JPanel to be added to the JFrame before starting
{
super.addNotify(); // creates the peer
startGame(); // start the thread
}
/**
* Starts the animation loop
*/
private void startGame()
// initialise and start the thread
{
if (animator == null || !running) {
animator = new Thread(this);
animator.start();
}
} // end of startGame()
// ------------- game life cycle methods ------------
// called by the JFrame's window listener methods
public void resumeGame()
// called when the JFrame is activated / deiconified
{
isPaused = false;
}
public void pauseGame()
// called when the JFrame is deactivated / iconified
{
isPaused = true;
}
public void stopGame()
// called when the JFrame is closing
{
running = false;
}
// ----------------------------------------------
public void run()
/* The frames of the animation are drawn inside the while loop. */
{
long beforeTime, afterTime, timeDiff, sleepTime;
long overSleepTime = 0L;
int noDelays = 0;
long excess = 0L;
gameStartTime = System.nanoTime();
prevStatsTime = gameStartTime;
beforeTime = gameStartTime;
running = true;
while (running) {
gameUpdate();
//T Entering Game Render
System.out.println("Entering Game Render");
gameRender();
paintScreen();
afterTime = System.nanoTime();
timeDiff = afterTime - beforeTime;
sleepTime = (period - timeDiff) - overSleepTime;
if (sleepTime > 0) { // some time left in this cycle
try {
Thread.sleep(sleepTime / 1000000L); // nano -> ms
} catch (InterruptedException ex) {
}
overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
} else { // sleepTime <= 0; the frame took longer than the period
excess -= sleepTime; // store excess time value
overSleepTime = 0L;
if (++noDelays >= NO_DELAYS_PER_YIELD) {
Thread.yield(); // give another thread a chance to run
noDelays = 0;
}
}
beforeTime = System.nanoTime();
/*
* If frame animation is taking too long, update the game state
* without rendering it, to get the updates/sec nearer to the
* required FPS.
*/
int skips = 0;
while ((excess > period) && (skips < MAX_FRAME_SKIPS)) {
excess -= period;
gameUpdate(); // update state but don't render
skips++;
}
framesSkipped += skips;
storeStats();
}
printStats();
System.exit(0); // so window disappears
} // end of run()
/**
* Renders to the backbuffer
*/
private void gameRender() {
if (dbImage == null) {
dbImage = createImage(PWIDTH, PHEIGHT);
if (dbImage == null) {
System.out.println("dbImage is null");
return;
} else
dbg = dbImage.getGraphics();
//T
System.out.println("dbg set");
}
// clear the background
dbg.setColor(Color.white);
dbg.fillRect(0, 0, PWIDTH, PHEIGHT);
//T
simpleRender(dbg);
if (gameOver)
gameOverMessage(dbg);
} // end of gameRender()
/**
* Paints the back buffer
*/
private void paintScreen()
// use active rendering to put the buffered image on-screen
{
Graphics g;
try {
g = this.getGraphics();
if ((g != null) && (dbImage != null))
g.drawImage(dbImage, 0, 0, null);
g.dispose();
} catch (Exception e) {
System.out.println("Graphics context error: " + e);
}
} // end of paintScreen()
/**
* Should be update the game state
*/
private void gameUpdate() {
if (!isPaused && !gameOver)
simpleUpdate();
} // end of gameUpdate()
private void storeStats() {
frameCount++;
statsInterval += period;
if (statsInterval >= MAX_STATS_INTERVAL) { // record stats every
// MAX_STATS_INTERVAL
long timeNow = System.nanoTime();
timeSpentInGame = (int) ((timeNow - gameStartTime) / 1000000000L);
long realElapsedTime = timeNow - prevStatsTime; // time since last
// stats collection
totalElapsedTime += realElapsedTime;
totalFramesSkipped += framesSkipped;
double actualFPS = 0; // calculate the latest FPS and UPS
double actualUPS = 0;
if (totalElapsedTime > 0) {
actualFPS = (((double) frameCount / totalElapsedTime) * 1000000000L);
actualUPS = (((double) (frameCount + totalFramesSkipped) / totalElapsedTime) * 1000000000L);
}
// store the latest FPS and UPS
fpsStore[(int) statsCount % NUM_FPS] = actualFPS;
upsStore[(int) statsCount % NUM_FPS] = actualUPS;
statsCount = statsCount + 1;
double totalFPS = 0.0; // total the stored FPSs and UPSs
double totalUPS = 0.0;
for (int i = 0; i < NUM_FPS; i++) {
totalFPS += fpsStore[i];
totalUPS += upsStore[i];
}
if (statsCount < NUM_FPS) { // obtain the average FPS and UPS
averageFPS = totalFPS / statsCount;
averageUPS = totalUPS / statsCount;
} else {
averageFPS = totalFPS / NUM_FPS;
averageUPS = totalUPS / NUM_FPS;
}
framesSkipped = 0;
prevStatsTime = timeNow;
statsInterval = 0L; // reset
}
} // end of storeStats()
private void printStats() {
System.out.println("Frame Count/Loss: " + frameCount + " / "
+ totalFramesSkipped);
System.out.println("Average FPS: " + df.format(averageFPS));
System.out.println("Average UPS: " + df.format(averageUPS));
System.out.println("Time Spent: " + timeSpentInGame + " secs");
} // end of printStats()
/**
* Should implement game specific rendering
*
* #param g
*/
protected abstract void simpleRender(Graphics g);
/**
* Should display a game specific game over message
*
* #param g
*/
protected abstract void gameOverMessage(Graphics g);
protected abstract void simpleUpdate();
/**
* This just gets called when a click occurs, no default behavior
*/
protected abstract void mousePress(int x, int y);
/**
* Should be overridden to initialize the game specific components
*/
protected abstract void simpleInitialize();
} // end of GamePanel class
Racer Class:
import java.awt.*;
import java.awt.geom.*;
public class Racer extends Rectangle {
//Only method that will likely be common between
//the two areas. This presumably draws to screen
//Size of Car
private static final int carSize = 20;
//Changing racer position from array to x and y coordinates
private int pWidth, pHeight; // panel dimensions
private long startTime; // in ms
public Racer (int pW, int pH){
this.width = pW;
this.height = pH;
//Meant to start racer in the center of the screen
//But it does not
this.x = pW/2;
this.y = pW/2;
}
public void draw(Graphics g){
g.setColor(Color.blue);
g.fillRect( x, y, carSize, carSize);
}
public int getRacerPositionX() {
return x;
}
public void setRacerPositionX(int x) {
this.x = x;
}
public int getRacerPositionY() {
return y;
}
public void setRacerPositionY(int y) {
this.y = y;
}
}
Main Racer:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main_Racer extends JFrame implements WindowListener
{
private static int DEFAULT_FPS = 80;
private RacingPanel rp;
//Let's leave now and make the panel
//Q: Just a value; why JTextField instead of int?
private JTextField jtfBox;
//Q: Just a value; why JTextField instead of int?
private JTextField jtfTime;
//Main_Racer Constructor
public Main_Racer(long period)
{
//Q: Gotta find this constructor
super("The Main Racder");
//Q:What does the argument do?
makeGUI(period);
addWindowListener( this);
pack();
setResizable(false);
setVisible(true);
}
//Q: Warrants an in depth look
private void makeGUI(long period)
{
Container c = getContentPane(); // default BorderLayout used
rp = new RacingPanel(this, period);
c.add(rp, "Center");
JPanel ctrls = new JPanel(); // a row of textfields
ctrls.setLayout( new BoxLayout(ctrls, BoxLayout.X_AXIS));
//Keeps track of time. Might still be useful
jtfTime = new JTextField("Time Spent: 0 secs");
jtfTime.setEditable(false);
ctrls.add(jtfTime);
c.add(ctrls, "South");
} // end of makeGUI()
//Pretty straing forward
public void setTimeSpent(long t)
{ jtfTime.setText("Time Spent: " + t + " secs"); }
// QQQ -----------------Going to copy the window listening methods, as probably n
//need em all
public void windowActivated(WindowEvent e)
{ rp.resumeGame(); }
public void windowDeactivated(WindowEvent e)
{ rp.pauseGame(); }
public void windowDeiconified(WindowEvent e)
{ rp.resumeGame(); }
public void windowIconified(WindowEvent e)
{ rp.pauseGame(); }
public void windowClosing(WindowEvent e)
{ rp.stopGame(); }
public void windowClosed(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
//=================================================================================
public static void main(String args[])
{
int fps = DEFAULT_FPS;
if (args.length != 0)
fps = Integer.parseInt(args[0]);
long period = (long) 1000.0/fps;
System.out.println("fps: " + fps + "; period: " + period + " ms");
new Main_Racer(period*1000000L); // ms --> nanosecs
}
} // end of WormChase class
Any reason why collision detection only works on one side?
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.
Im trying to make a square follow my mouse after i left click on it . When i right click the square should stop following my mouse .
My program detects that im clicking inside the square , but for some reason it doesn't update its position based on Mouse.getDX/DY .
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
public class SimpleOGLRenderer {
private static boolean somethingIsSelected = false;
public static void main(String args[]) {
try {
Display.setDisplayMode(new DisplayMode(800,600));
Display.setTitle("Hello World");
Display.create();
} catch (LWJGLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Initializare OPENGL
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 800, 600, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
while(!Display.isCloseRequested())
{
//Render
glClear(GL_COLOR_BUFFER_BIT);
Box box = new Box(100,100);
if(Mouse.isButtonDown(0) && box.inBounds(Mouse.getX(), Display.getHeight()-Mouse.getY()-1) && !somethingIsSelected)
{
System.out.println("Box clicked");
somethingIsSelected = true;
box.selected = true;
}
if(Mouse.isButtonDown(1))
{
box.selected = false;
somethingIsSelected = false;
System.out.println("Box released");
}
if(box.selected)
{
box.update(Mouse.getDX(), -Mouse.getDY());
}
box.drawQuad();
Display.update();
// Display.sync(60);
}
Display.destroy();
}
private static class Box{
public int x, y;
public boolean selected=false;
Box(int x, int y) {
this.x = x;
this.y = y;
}
void drawQuad()
{
glBegin(GL_QUADS);
glVertex2i(x,y);
glVertex2i(x+50,y);
glVertex2i(x+50,y+50);
glVertex2i(x,y+50);
glEnd();
}
void update(int dx,int dy)
{
x = x + dx;
y = y + dy;
}
boolean inBounds(int mouseX, int mouseY) {
return mouseX > x && mouseX < x + 50 && mouseY > y && mouseY < y + 50;
}
}
}
The program works fine and the Box does update!
The problem lies in where you create the Box.
while(!Display.isCloseRequested())
{
//Render
glClear(GL_COLOR_BUFFER_BIT);
Box box = new Box(100,100);
...
See, you create the Box inside the main-loop, therefore it gets deleted and initialized each time it loops. Simply move it outside the loop, so it doesn't get initialized at every loop, like this.
Box box = new Box(100,100);
while(!Display.isCloseRequested())
{
//Render
glClear(GL_COLOR_BUFFER_BIT);
...