I have been working in Java for the past week, and I am taking an online/offline course where we work with Processing. This code is supposed to create a rocket that would fly around the screen based on the input of the user. However, it always flies backwards, and the only way to prevent it from flying backwards is to press forward. Even then, it only stands still. Through some testing, we have found out that the movingBackward variable is constantly triggered, but there seems to be no reason for it. My teacher and I are stumped, and any and all suggestions/advice are greatly appreciated.
package processing2;
import processing.core.PApplet;
public class Processing2 extends PApplet
{
private static final long serialVersionUID = 1L;
public float rotationAmount = 180;
public boolean rotateLeft = false;
public boolean rotateRight = false;
public float speed = 10;
public float x = 400;
public float y = 350;
public boolean moveForward = false;
public boolean movingBackward = false;
public boolean moving = false;
public void setup()
{
size(800, 700);
}
public void draw()
{
background(255, 255, 255);
move();
changeRotation();
translate(x, y);
rotate(rotationAmount);
drawRocketShip();
}
public int rocketX = 0;
public int rocketY = 0;
public void drawRocketShip()
{
stroke(0, 149, 185);
fill(0, 149, 185);
rect(rocketX, rocketY, 75, 50);
triangle(rocketX + 75, rocketY + 1, 100, rocketY + 25, rocketX + 75, rocketY + 49);
fill(255, 255, 255);
ellipse(rocketX + 60, rocketY + 25, 30, 15);
stroke(0, 149, 185);
strokeWeight(3);
fill(255, 255, 255);
triangle(rocketX + 25, rocketY, rocketX - 15, rocketY - 25, rocketX, rocketY);
triangle(rocketX + 25, rocketY + 50, rocketX - 15, rocketY + 75, rocketX, rocketY + 50);
if(moving)
{
fill(255, 0, 0);
noStroke();
triangle(rocketX - 10, rocketY + 10, rocketX - 30, rocketY + 25, rocketX - 10, rocketY + 40);
}
}
public void keyPressed()
{
if(key == 'a')
{
rotateLeft = true;
}
if(key == 'd')
{
rotateRight = true;
}
if(key == 'w')
{
moveForward = true;
moving = true;
}
if (key == 's');
{
movingBackward = true;
moving = true;
}
}
public void keyReleased()
{
if(key =='a')
{
rotateLeft = false;
}
if(key == 'd')
{
rotateRight = false;
}
if(key == 'w')
{
moveForward = false;
moving = false;
}
if (key == 's');
{
movingBackward = false;
moving = false;
}
}
public void move()
{
if(moveForward)
{
x += speed * cos(rotationAmount);
y += speed * sin(rotationAmount);
}
if(movingBackward);
{
x += -speed * cos(rotationAmount);
y += -speed * sin(rotationAmount);
}
}
public void changeRotation()
{
if(rotateLeft)
{
rotationAmount -= .08;
if(rotationAmount < 0)
{
rotationAmount = 2 * PI;
}
}
if(rotateRight)
{
rotationAmount += .08;
if(rotationAmount > 2* PI)
{
rotationAmount = 0;
}
}
}
}
if(movingBackward);
you are effectively telling java to do nothing if movingBackward is true. As a result, it will treat the curly braces after as a simple block that has no particular syntactic effect and is always processed. Remove the semicolon and it should work.
Same issue at both instances of
if (key == 's');
I personally prefer placing opening braces on the same line as the if (or try, catch, else, etc...), which makes mistakes like these easier to spot. That's preference though.
Related
For some reason there are two player speeds in my game Orange Quest. What I mean by this is when I test my game in eclipse and my headphones are off. The game goes twice as fast as when my headphones are on.
I sent the game to my friend and he also experiences the same problems. I've tried to debug the code to see if there was a something wrong with it, but I didn't see any problem. I also tried to adjust the player speed but that didn't help either, as it was still going twice as fast when my headphones were off.
Here is the code for the game panel
Oh yah, by the way the frame is 700 by 700
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class GamePanel extends JPanel implements ActionListener {
/**
*
*/
private static final long serialVersionUID = 1L;
Player player;
boolean running = true;
CopyOnWriteArrayList<Wall> walls = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList<LavaWall> lavaWalls = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList<Enemy> enemies = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList<Orange> oranges = new CopyOnWriteArrayList<>();
java.util.Timer gameTimer;
int cameraX;
int offset;
int count = 0;
int index = 0;
int set;
int s = 50;
int r = 75;
BufferedImage dirt;
BufferedImage grass;
BufferedImage lava;
BufferedImage cloud;
BufferedImage spike;
BufferedImage undergroundLava;
BufferedImage character;
BufferedImage thumbnail;
JLabel timeLabel = new JLabel();
JLabel orangeLabel = new JLabel(": 0/7");
double orangeCount = 0;
int elapsedTime = 0;
int minutes = 0;
int seconds = 0;
int ms = 0;
String minutesString = String.format("%02d", minutes);
String secondsString = String.format("%02d", seconds);
String msString = String.format("%02d", ms);
java.util.Timer timer = new java.util.Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
elapsedTime += 10;
minutes = (elapsedTime / 60000);
seconds = (elapsedTime / 1000) % 60;
ms = (elapsedTime / 10) % 100;
minutesString = String.format("%02d", minutes);
secondsString = String.format("%02d", seconds);
msString = String.format("%02d", ms);
timeLabel.setText(minutesString + ":" + secondsString + ":" + msString);
}
};
GamePanel() {
if (running) {
player = new Player(400, 300, this);
reset();
setLayout(null);
gameTimer = new java.util.Timer();
add(player.death);
player.death.setBounds(550, 15, 300, 100);
player.death.setFont(new Font("Verdana", Font.PLAIN, 20));
add(orangeLabel);
orangeLabel.setBounds(320, 15, 200, 50);
orangeLabel.setFont(new Font("Verdana", Font.PLAIN, 20));
gameTimer.schedule(new TimerTask() {
#Override
public void run() {
try {
if (walls.get(walls.size() - 1).x < 800) {
offset += 700;
makeWalls(offset);
}
player.set();
for (Wall wall : walls)
wall.set(cameraX);
for (int i = 0; i < walls.size(); i++) {
if (walls.get(i).x < -800)
walls.remove(i);
}for(Enemy enemy : enemies)
enemy.set(cameraX);
for (LavaWall lava : lavaWalls)
lava.set(cameraX);
for (int i = 0; i < lavaWalls.size(); i++) {
if (lavaWalls.get(i).x < -800)
lavaWalls.remove(i);
}
for(Orange orange : oranges)
orange.set(cameraX);
for(int i = 0; i < oranges.size(); i++) {
if(oranges.get(i).x < -800)
oranges.remove(i);
}
repaint();
} catch (Throwable e) {
e.printStackTrace();
}
}
}, 0, 17);
add(timeLabel);
timeLabel.setText(minutesString + ":" + secondsString + ":" + msString);
timeLabel.setBounds(10, 15, 300, 100);
timeLabel.setFont(new Font("Verdana", Font.PLAIN, 25));
timer.scheduleAtFixedRate(task, 0, 10);
} else if (!running) {
System.exit(0);
}
}
public void makeWalls(int offset) {
Random rnd = new Random();
try {
dirt = ImageIO.read(getClass().getResourceAsStream("/art/dirt block.png"));
grass = ImageIO.read(getClass().getResourceAsStream("/art/grass block.png"));
lava = ImageIO.read(getClass().getResourceAsStream("/art/lava block.png"));
cloud = ImageIO.read(getClass().getResourceAsStream("/art/cloud block.png"));
undergroundLava = ImageIO.read(getClass().getResourceAsStream("/art/underground lava.png"));
thumbnail = ImageIO.read(getClass().getResourceAsStream("/art/thumbnail.png"));
} catch (Exception e) {
e.printStackTrace();
}
if (count == 7) {
oranges.add(new Orange(offset + 50, 500, s, s, thumbnail));
for (int i = 1; i <= 14; i++) {
walls.add(new Wall(offset + i * 50, 600, s, s, grass));
walls.add(new Wall(offset + i * 50, 650, s, s, dirt));
}
}
else if(count != 10) {
if (index == 0) {
for (int i = 1; i <= 14; i++) {
walls.add(new Wall(offset + i * 50, 600, s, s, grass));
walls.add(new Wall(offset + i * 50, 650, s, s, dirt));
if(i == 6) {
enemies.add(new Enemy(offset + 350, 550, r, s));
}
}
set = 0;
} else if (index == 1) {
for (int j = 1; j <= 14; j++) {
for (int i = 650; i >= 350; i -= 50) {
if (i == 350)
walls.add(new Wall(offset, i, s, s, grass));
else
walls.add(new Wall(offset, i, s, s, dirt));
}
offset += 50;
set = 1;
}
} else if (index == 2) {
if(set == 0) {
walls.add(new Wall(offset - 50, 500, s, s, cloud));
walls.add(new Wall(offset - 200, 400, s, s, cloud));
walls.add(new Wall(offset, 300, s, s, cloud));
for (int i = 0; i < 9; i++) {
walls.add(new Wall(offset + 300 + i * 50, 600, s, s, grass));
walls.add(new Wall(offset + 300 + i * 50, 650, s, s, dirt));
}
}else {
for (int i = 1; i <= 14; i++) {
walls.add(new Wall(offset + i * 50, 600, s, s, grass));
walls.add(new Wall(offset + i * 50, 650, s, s, dirt));
if(i == 6) {
enemies.add(new Enemy(offset + 350, 550, r, s));
}
}
}
} else if (index == 3) {
for (int i = 1; i <= 2; i++) {
walls.add(new Wall(offset + i * 50, 600, s, s, grass));
walls.add(new Wall(offset + i * 50, 650, s, s, dirt));
}
lavaWalls.add(new LavaWall(offset + 150, 600, s, s, lava));
lavaWalls.add(new LavaWall(offset + 200, 600, s, s, lava));
lavaWalls.add(new LavaWall(offset + 250, 600, s, s, lava));
lavaWalls.add(new LavaWall(offset + 300, 600, s, s, lava));
lavaWalls.add(new LavaWall(offset + 350, 600, s, s, lava));
lavaWalls.add(new LavaWall(offset + 150, 650, s, s, undergroundLava));
lavaWalls.add(new LavaWall(offset + 200, 650, s, s, undergroundLava));
lavaWalls.add(new LavaWall(offset + 250, 650, s, s, undergroundLava));
lavaWalls.add(new LavaWall(offset + 300, 650, s, s, undergroundLava));
lavaWalls.add(new LavaWall(offset + 350, 650, s, s, undergroundLava));
for (int i = 6; i <= 12; i++) {
walls.add(new Wall(offset + 100 + i * 50, 600, s, s, grass));
walls.add(new Wall(offset + 100 + i * 50, 650, s, s, dirt));
}
}
for(Wall wall : walls) {
for(LavaWall lava : lavaWalls) {
if(lava.hitBox.getBounds() == wall.hitBox.getBounds()) {
lavaWalls.remove(lava);
}
}
}
count++;
index = rnd.nextInt(4);
}
}
public void reset() {
count = 0;
index = 0;
player.x = 200;
player.y = 150;
cameraX = 150;
player.xspeed = 0;
player.yspeed = 0;
walls.clear();
enemies.clear();
lavaWalls.clear();
oranges.clear();
offset = -150;
makeWalls(offset);
player.isDed = false;
}
public void paint(Graphics g) {
try {
super.paint(g);
Graphics2D gtd = (Graphics2D) g;
player.draw(gtd);
for(int i = 0; i < walls.size(); i++) {
try {
walls.get(i).draw(gtd);
} catch (Throwable e) {
}
}for(Enemy enemy : enemies)
enemy.draw(gtd);
for(LavaWall lava : lavaWalls)
lava.draw(gtd);
g.drawImage(thumbnail, 270, 15, 50, 50, null);
for(Orange orange : oranges)
orange.draw(gtd);
} catch (Throwable e) {
e.printStackTrace();
}
}
#Override
public void actionPerformed(ActionEvent e) {
}
public void keyPressed(KeyEvent e) {
if (e.getKeyChar() == 'a')
player.keyLeft = true;
if (e.getKeyChar() == 'w' || e.getKeyCode() == 32)
player.keyUp = true;
if (e.getKeyChar() == 's')
player.keyDown = true;
if (e.getKeyChar() == 'd')
player.keyRight = true;
if (e.getKeyChar() == 'h')
Player.keyGlide = true;
if (e.getKeyChar() == 'j')
player.keyMega = true;
if (e.getKeyChar() == 'l')
player.keyRush = true;
}
public void keyReleased(KeyEvent e) {
if (e.getKeyChar() == 'a')
player.keyLeft = false;
if (e.getKeyChar() == 'w' || e.getKeyCode() == 32)
player.keyUp = false;
if (e.getKeyChar() == 's')
player.keyDown = false;
if (e.getKeyChar() == 'd')
player.keyRight = false;
if (e.getKeyCode() == 27)
System.exit(0);
if (e.getKeyChar() == 'h')
Player.keyGlide = false;
if (e.getKeyChar() == 'j')
player.keyMega = false;
if (e.getKeyChar() == 'l')
player.keyRush = false;
}
}
and here is the player code
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.*;
public class Player {
GamePanel panel;
int x;
int y;
int width;
int height;
double xspeed;
double yspeed;
boolean keyLeft;
boolean keyRight;
boolean keyUp;
static boolean keyGlide;
boolean keyDown;
boolean keyMega;
boolean keyRush;
boolean falling;
boolean isDeathSound;
boolean isDed;
Graphics2D gtd;
long time = 0;
Timer timer;
long start;
long stop;
double deaths = 0;
JLabel death = new JLabel("Deaths: 0");
Rectangle hitBox;
long waitTime;
static Clip clip;
static boolean onGround;
Player(){
}
Player(int x, int y, GamePanel panel){
this.panel = panel;
this.x = x;
this.y = y;
width = 50;
height = 100;
hitBox = new Rectangle(x, y, width, height);
}
public void set() throws Throwable{
Iterator<Orange> orangeItr = panel.oranges.iterator();
if(keyLeft && keyRight || !keyLeft && !keyRight) xspeed *= 0.8;
else if(keyLeft && !keyRight)xspeed--;
else if(keyRight && !keyLeft)xspeed++;
if(keyUp && keyGlide) {keyUp = false;}
if(yspeed > 0)onGround = false;
if(keyMega && keyGlide) {keyMega = false;}
if(onGround && keyGlide)keyGlide = false;
if(xspeed > 0 && xspeed < 0.75)xspeed = 0;
if(xspeed < 0 && xspeed > -0.75)xspeed = 0;
if(xspeed > 7 && !keyRush)xspeed = 7;
if(xspeed < -7 && !keyRush)xspeed = -7;
if(xspeed > 12 && keyRush)xspeed = 12;
if(xspeed < -12 && keyRush)xspeed = -12;
if(yspeed < -12.75) yspeed = -12.75;
if(keyUp && onGround) {
jumpSound();
hitBox.y++;
onGround = false;
for(Wall wall : panel.walls) {
if(wall.hitBox.intersects(hitBox)) {
yspeed = -8;
}
}hitBox.y--;
}if(keyMega && onGround) {
megaSound();
onGround = false;
hitBox.y++;
for(Wall wall : panel.walls) {
if(wall.hitBox.intersects(hitBox)) yspeed = -12.75;
}hitBox.y--;
}
yspeed += 0.3;
if(keyGlide && !onGround && yspeed > 1.2) {
glideSound();
yspeed -= 0.25;
}if(keyDown && !onGround) {
yspeed += 0.4;
}
//horizontal collision
hitBox.x += xspeed;
for(Wall wall : panel.walls) {
if(hitBox.intersects(wall.hitBox)) {
hitBox.x -= xspeed;
while(!wall.hitBox.intersects(hitBox))hitBox.x += Math.signum(xspeed);
hitBox.x -= Math.signum(xspeed);
panel.cameraX += x - hitBox.x;
xspeed = 0;
hitBox.x = x;
}
}
for(Orange orange : panel.oranges){
isDed = false;
if(hitBox.intersects(orange.hitBox)) {
isDed = false;
if(panel.orangeCount != 6) {
isDed = false;
keyGlide = false;
hitBox.x -= xspeed;
while(!orange.hitBox.intersects(hitBox))hitBox.x += Math.signum(xspeed);
hitBox.x -= Math.signum(xspeed);
panel.cameraX += x - hitBox.x;
xspeed = 0;
x = hitBox.x;
panel.orangeCount++;
panel.reset();
panel.orangeLabel.setText(": " +(int)panel.orangeCount + "/7");
onGround = true;
isDed = false;
deathSound();
}
else {
keyGlide = false;
hitBox.x -= xspeed;
while(!orange.hitBox.intersects(hitBox))hitBox.x += Math.signum(xspeed);
hitBox.x -= Math.signum(xspeed);
xspeed = 0;
x = hitBox.x;
onGround = true;
panel.orangeCount++;
panel.orangeLabel.setText(": " + (int)panel.orangeCount + "/7");
orangeSound();
System.out.println("Well done");
Thread.sleep(1100);
System.out.print("your time is ");
System.out.println(panel.timeLabel.getText());
System.out.println("you died " + (int)deaths + " time(s)");
System.exit(0);
}
}
}
//vertical collision
hitBox.y += yspeed;
for(Wall wall : panel.walls) {
if(hitBox.intersects(wall.hitBox)) {
keyGlide = false;
hitBox.y -= yspeed;
while(!wall.hitBox.intersects(hitBox))hitBox.y += Math.signum(yspeed);
hitBox.y -= Math.signum(yspeed);
yspeed = 0;
y = hitBox.y;
onGround = true;
}
}
try {
for(LavaWall lava : panel.lavaWalls) {
if(hitBox.intersects(lava.hitBox)) {
isDed = true;
isDeathSound = true;
keyGlide = false;
hitBox.y -= yspeed;
while(!lava.hitBox.intersects(hitBox))hitBox.y += Math.signum(yspeed);
hitBox.y -= Math.signum(yspeed);
yspeed = 0;
y = hitBox.y;
onGround = true;
isDed = true;
die();
}
}
for(Orange orange : panel.oranges){
isDed = false;
if(hitBox.intersects(orange.hitBox)) {
isDed = false;
if(!(panel.orangeCount == 7)) {
keyGlide = false;
hitBox.y -= yspeed;
while(!orange.hitBox.intersects(hitBox))hitBox.y += Math.signum(yspeed);
hitBox.y -= Math.signum(yspeed);
yspeed = 0;
y = hitBox.y;
onGround = true;
panel.orangeCount++;
panel.reset();
panel.orangeLabel.setText(": " +(int)panel.orangeCount + "/7");
isDed = false;
deathSound();
}
else if(panel.orangeCount == 7) {
keyGlide = false;
hitBox.y -= yspeed;
while(!orange.hitBox.intersects(hitBox))hitBox.y += Math.signum(yspeed);
hitBox.y -= Math.signum(yspeed);
yspeed = 0;
y = hitBox.y;
onGround = true;
panel.orangeCount++;
panel.orangeLabel.setText(": " + (int)panel.orangeCount + "/7");
orangeSound();
System.out.println("Well done");
Thread.sleep(1100);
System.out.print("your time is ");
System.out.println(panel.timeLabel.getText());
System.out.println("you died " + (int)deaths + " time(s)");
Thread.sleep(4500);
System.out.println("press v to exit");
}
}
}
}catch(Throwable e) {
}
panel.cameraX -= xspeed;
y += yspeed;
hitBox.x = x;
hitBox.y = y;
//death code
if(y > 800) {
isDed = true;
onGround = true;
die();
}enemyScript();
}void enemyScript() {
for(Enemy enemy : panel.enemies) {
if(hitBox.intersects(enemy.hitBox)) {
isDed = true;
isDeathSound = true;
keyGlide = false;
hitBox.y -= yspeed;
while(!enemy.hitBox.intersects(hitBox))hitBox.y += Math.signum(yspeed);
hitBox.y -= Math.signum(yspeed);
yspeed = 0;
y = hitBox.y;
onGround = true;
isDed = true;
die();
}
}
}
void jumpSound(){
soundEffect("res\\musicAndSoundEffects\\jump.wav");
}void megaSound(){
soundEffect("res\\musicAndSoundEffects\\megajump.wav");
}void glideSound(){
soundEffect("res\\musicAndSoundEffects\\shorterGlide.wav");
}void deathSound(){
if(isDed) {
soundEffect("res\\musicAndSoundEffects\\death.wav");
}else if(!isDed) {
soundEffect("res\\musicAndSoundEffects\\orangeSound.wav");
}
}void notDie(){
stopSound();
}
void orangeSound(){
soundEffect("res\\musicAndSoundEffects\\orangeSound.wav");
}void stopSound(){
clip.stop();
}
void die() {
deathSound();
panel.reset();
deaths++;
death.setText("Deaths: " + (int)deaths);
onGround = true;
}
static void soundEffect(String filePath) {
try {
File file = new File(filePath);
AudioInputStream sound = AudioSystem.getAudioInputStream(file);
clip = AudioSystem.getClip();
if(onGround && !filePath.equals("res\\musicAndSoundEffects\\shorterGlide.wav")) {
clip.open(sound);
clip.setFramePosition(0);
clip.start();
}else if(filePath.equals("res\\musicAndSoundEffects\\shorterGlide.wav")) {
clip.open(sound);
clip.setFramePosition(0);
clip.start();
}
}catch(Exception e) {
JOptionPane.showMessageDialog(null, e.getStackTrace());
}
}
public void draw(Graphics2D g) {
g.setColor(Color.BLACK);
g.fillRect(x, y, width, height);
}
}
for anyone who knows the answer to this. Please comment the problem and not the answer so that I can learn. thanks
In broad strokes:
Because you're using a java.util.Timer and it is just the wrong tool for the job.
Let's say you want a game to run smoothly, but not slam the CPU of even the most powerful machine imaginable, and also to run as well as it can if the system it runs on is insufficient (that last one is important; even if a system is plenty powerful to run the game, sometimes you get a 'blip' of underperformance because of other stuff the computer was doing, such as when you plug in a USB stick and all sorts of driver shenanigans occurs in the background).
To accomplish these things, you need two crucial properties:
Timing related to the gameplay (such as, if one of the players is moving northbound, the amount of movement that occurs) should be based entirely on 'time passed', and be unaffected by the amount of time required to actually redraw parts of the screen, nor should it be affected by how many 'loops' of screen refresh you manage to squeeze into a single second.
Timing related to rendering needs to go fast as possible, but needs a breaking system: BEFORE you begin the task of 'update game state then render the state to the screen', you should calculate the timing at which that should all be done. Then, once you are done with one loop of the game (adjust game state and rendering all that), you check whether you 'beat the clock'. If you did, THEN wait. In other words, instead of asking a timer to wait a fixed amount of time before doing the next game loop, the amount of time to wait needs to take into account you took some time to adjust the game state and render things.
Here's some example code of a basic game loop. Just use it for inspiration, it doesn't fit verbatim into the code you already have.
class Example {
private static final long NANOS_PER_MILLI =
TimeUnit.MILLISECONDS.toNanos(1);
private static final long NANOS_PER_FRAME =
TimeUnit.SECONDS.toNanos(1) / 60;
private static final long ADJUST_EXPECTATIONS_TRESHOLD =
NANOS_PER_FRAME * 5;
private long start = System.nanoTime();
private long frameCounter = 0;
public void run() {
while (running) {
gameLoop();
}
}
void gameLoop() {
frameCounter++;
long target = startTime + NANOS_PER_FRAME * frameCounter;
// target now holds the exact time at which point we should
// be done with this game loop.
recalcGameState();
redrawStuff();
long end = System.nanoTime();
long delta = target - System.nanoTime();
if (delta > 0) {
// We had time to spare!
// Let's sleep most of that away, giving us
// a little bit of leeway (5msec worth) in case the system is
// going to blip on us.
// Also, CPU waiting is generally granularized at millis,
// so let's convert to millis first, and be 5 millis 'early'
long millisToWait = (delta / NANOS_PER_MILLI) - 5;
if (millisToWait > 0) sleep(millisToWait);
else if (-delta > READJUST_EXPECTATIONS_TRESHOLD) {
// Rats - we missed the boat, and by a lot!
// we are over 5 frames behind, let's readjust
// expectations and slow down the game logic, too:
start = end;
frameCounter = 0;
}
}
}
}
The above code will reliably render at 60 gameloops every second, (that 5msec leeway will adjust itself on the next loop, as that would just mean you get there even faster and thus wait longer) - and will 'catch up' on a blip for at most 5 frames (catching up a ton of frames after a long blip is usually not a good idea, so we limit the catchup mechanism).
Usually when you're forced into readjustment you may want to adjust the game logic's clocks as well (it is a bit unfair for a player to slam into a wall that was way ahead of them because their CPU just decided to doze off for a second, unlikely as that is, whilst they couldn't steer or even see anything!) - so, have a ball with gameStart.
NB: nanoTime is used and not System.currentTimeMillis(), because System.CTM represents the system clock, which means it will drastically change when the user resets their time - modern computers update their clocks by way of a network time server, so this happens all the time (heh), and means that looking at it for frame timing is a bad idea. From time to time the game will do mad glitching when the NTP daemon adjusted the clocks. nanoTime is more or less reflecting 'CPU uptime' and does not get modified when the system clock is adjusted.
NB2: If you need 'frameCounter' to represent game turns, you can't just reset it like this; instead, figure out how many frames you want to adjust by, and then add that many NANOS_PER_FRAME to 'start' instead.
For my class I need to create a one player pong game. We need to use what we've learned so its simple code and the problem is, while the "while loop" is running, my Keydown thread doesn't seem to work. My teacher isn't helpful at all so that's why i'm here. Please help by only using methods and such that are used in my program.
I've tried moving the ball code into a run thread but i can never seem to actually get that thread running.
public class PongGame extends Applet {
int startup = 0;
int x = 400;
int y = 500;
int x2 = (int) (Math.random() * (600 + 1));
int y2 = (int) (Math.random() * (600 + 1));
int xVelocity = 1;
int yVelocity = 1;
int x2Velocity = 1;
int y2Velocity = 1;
int curry = 700;
int currx = 600;
int counter = 2;
#Override
public void init() {
setSize(1440, 900);
setBackground(Color.black);
setFont(new Font("Helvetica", Font.BOLD, 36));
}
#Override
public boolean keyDown(Event evt, int key) {
startup = startup + 1;
repaint();
if (key == Event.RIGHT) {
currx += 10;
}
if (key == Event.LEFT) {
currx -= 10;
}
if (currx == 1400) {
currx = 10;
}
if (currx == 20) {
currx = 1399;
}
repaint();
return false;
}
public void run(Graphics g) {
startup = 0;
while (counter > 0) {
try {
Thread.sleep(30);
} catch (InterruptedException e) {
}
x += xVelocity;
y += yVelocity;
g.setColor(Color.blue);
g.fillRect(currx, curry, 300, 25);
g.setColor(Color.red);
g.fillOval(x, y, 30, 30);
for (int j = 0; j < 20000000; j++);
g.setColor(Color.black);
g.fillOval(x, y, 30, 30);
//Bounce the ball off the wall or paddle
if (x >= 1400 || x <= 0) {
xVelocity = -xVelocity;
}
if (y >= 800 || y <= 0) {
yVelocity = -yVelocity;
}
if (((y == 675)) && ((currx <= x) && (currx + 300) >= x)) {
yVelocity = -yVelocity;
y = y - 10;
repaint();
}
}
}
public void paint(Graphics g) {
if (startup == 0) {
g.setColor(Color.white);
g.drawString("Welcome To PONG", 0, 100);
g.drawString("Created by Caden Anton", 0, 200);
g.drawString("copyright May 3rd, 2019 ©", 0, 300);
g.drawString("Press any key to continue", 0, 400);
}
if (startup == 1) {
g.setColor(Color.white);
g.drawString("RULES:", 0, 100);
g.drawString("Press the arrwow keys to move the paddle", 0, 200);
g.drawString("Your objective is to keep the ball from touching the ground", 0, 300);
g.drawString("Once the ball hits the ground you lose the game", 0, 400);
}
if (startup >= 2) {
//Input Run thread start here.
}
}
}
im creating a 2d world which has a player that is in a rectangle shape and what im trying to do is when the player press space button it draws a block depending on his direction the problem is it only sets for one block and plus it deletes it after repaiting now i know my mistake is in paint method. what i wanna know how to make it draws the block everytime i press space without removing after repainting and can be set for multiple times i know i should use loop but i dont know exactly i should write it
private static final long serialVersionUID = -1401667790158007207L;
int playerx = 450;
int playery = 450;
int playerDirection = 0; //north = 0, west = 1, south = 2, east = 3
boolean setBlock;
public platform(){
super("2D game");
JPanel panel = new JPanel();
panel.setBackground(Color.white);
addKeyListener(this);
this.setContentPane(panel);
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2 = (Graphics2D)g;
Rectangle player = new Rectangle(playerx, playery, 50, 50);
g2.fill(player);
if(setBlock){
if(playerDirection == 0){
g2.fillRect(playerx, playery - 50, 50, 50);
}else if(playerDirection == 1){
g2.fillRect(playerx + 50, playery, 50, 50);
}else if(playerDirection == 2){
g2.fillRect(playerx, playery + 50, 50, 50);
}else if(playerDirection == 3){
g2.fillRect(playerx - 50, playery, 50, 50);
}
setBlock = false;
}
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP){
playerDirection = 0;
playery -=50;
repaint();
}
if(e.getKeyCode() == KeyEvent.VK_DOWN){
playerDirection = 2;
playery +=50;
repaint();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
playerDirection = 1;
playerx += 50;
repaint();
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
playerDirection = 3;
playerx -=50;
repaint();
}
if(e.getKeyCode() == KeyEvent.VK_SPACE){
setBlock = true;
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
You need to store your Blocks in a List. And add a new one when pressing Space Key. Then you can easily draw all of them in a for loop. Also remove that setBlock boolean because it makes no sense.
...
// introduce this class to hold a block
class Block{
public int x;
public int y;
public Block(int _x, int _y){
x = _x;
y = _y;
}
}
...
// boolean setBlock; // remove this boolean
ArrayList<Block> blocks = new ArrayList<Block>(); // list of all blocks
public platform(){...}
public void paint(Graphics g){
...
// if(setBlock){ // remove this boolean
if(playerDirection == 0){
g2.fillRect(playerx, playery, 50, 50);
}else if(playerDirection == 1){
g2.fillRect(playerx, playery, 50, 50);
}else if(playerDirection == 2){
g2.fillRect(playerx, playery, 50, 50);
}else if(playerDirection == 3){
g2.fillRect(playerx, playery, 50, 50);
}
// draw the blocks
for(Block b : blocks)
g2.fillRect(b.x, b.y, 50, 50);
// setBlock = false; // remove this boolean
//} // remove this boolean
}
public void keyPressed(KeyEvent e) {
...
if(e.getKeyCode() == KeyEvent.VK_SPACE){
// setBlock = true; // remove this boolean
// add a new block
blocks.add(new Block(playerx, playery));
repaint();
}
}
...
I'm currently working on a Project that shows a tortoise vs. hare race in real-time as an Applet. A random number is chosen, and the animals either move forward, backward, or not at all based on that number. My problem is getting the animals to be seen in real-time. It currently displays the images at their starting positions, and says who wins. Any pointers on how to get this done would be great.
my code:
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Color;
import java.awt.Font;
public class Project2 extends Applet
{
Image tortoise, hare;
Image scaledTortoise, scaledHare;
final int tortoiseYPos = 50, hareYPos = 400, SQUARE = 20, END = 1200;
int tortoiseXPos = 180, hareXPos = 180;
public void init()
{
tortoise = getImage(getDocumentBase(), "tortoise.gif");
hare = getImage(getDocumentBase(), "hare.gif");
scaledTortoise = tortoise.getScaledInstance(20, 50, Image.SCALE_SMOOTH);
scaledHare = hare.getScaledInstance(20, 50, Image.SCALE_SMOOTH);
}
public void paint(Graphics field)
{
drawField(field);
drawMoves(field);
field.setFont(new Font("Times New Roman", Font.ITALIC, 72));
//Display winner when they get to the finish line
if(tortoiseXPos >= END)
{
field.drawString("Tortoise Wins!!", 650, 240);
}
else if(hareXPos >= END)
{
field.drawString("Hare Wins!!", 650, 240);
}
}
public void drawField(Graphics field)
{
setBackground(Color.green);
Font f = new Font("Times New Roman", Font.BOLD, 48);
field.setFont(f);
field.drawString("Tortoise", 0, 75);
field.drawString("Hare", 0, 425);
//fill alternating black and white rectangles
field.setColor(Color.black);
int x = 180;
for(int i = 0; i < 50; i++)
{
field.fillRect(x, 50, SQUARE, 50);
field.fillRect(x, 400, SQUARE, 50);
x += (SQUARE);
}
field.drawImage(scaledTortoise, 180, tortoiseYPos, this);
field.drawImage(scaledHare, 180, hareYPos, this);
}
public void drawMoves(Graphics s)
{
while(tortoiseXPos < END && hareXPos < END)
{
int move = (int)(Math.random() * 10);
tortoiseMoves(move); hareMoves(move);
s.drawImage(scaledTortoise, tortoiseXPos, tortoiseYPos, this);
s.drawImage(scaledHare, hareXPos, hareYPos, this);
delay(); delay(); delay();
}
}
public void tortoiseMoves(int move)
{ //Moves for Tortoise, 180 is start, 1200 is finish
if(move <= 5)
{
tortoiseXPos += (3 * SQUARE);
}
else if(move <= 8)
{
tortoiseXPos += SQUARE;
}
else if(move <= 10)
{
tortoiseXPos -= (6 * SQUARE);
}
if(tortoiseXPos < 180)
{
tortoiseXPos = 180;
}
if(tortoiseXPos > END)
{
tortoiseXPos = END;
}
}
public void hareMoves(int move)
{ //Moves for Hare, 180 is start, 1200 is finish
if(move <= 2)
{
hareXPos += (9 * SQUARE);
}
else if(move <= 5)
{
hareXPos += (SQUARE);
}
else if(move <= 6)
{
hareXPos -= (12 * SQUARE);
}
else if(move <= 8)
{
hareXPos -= (2 * SQUARE);
}
else if(move <= 10)
{
hareXPos = hareXPos;
}
if(hareXPos < 180)
{
hareXPos = 180;
}
if(hareXPos > END)
{
hareXPos = END;
}
}
public void delay()
{
for(int i = 0; i <= 90000000; i++)
{
}
}
}
I should note that I am not familiar with and should not be using java swing, as I am only supposed to be using awt.
The problem is with your delay function. Entering a loop keeps the applet running your code and it does not get a chance to render the display between moves. If you allow the Thread that your applet is running in to sleep, then that gives it a chance to display as it runs.
public void delay()
{
try {
Thread.sleep(100);
} catch (Exception e) {}
}
I'm working on a simple Android game.
When you press play, a timer counts down from 30, and once the timer hits zero, I want to call the function goToGameOver(). I can't seem to get a Handler working properly so I tried out the standard Timer class and it's not even close to real-time.
Also, as the timer counts down, I'd like to pass the time remaining into a global variable x every second, so that I can paint it onto the screen in a separate method.
Any thoughts on how I can best approach this? Thanks!
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
x = millisUntilFinished / 1000;
}
public void onFinish() {
goToGameOver();
} }.start();
EDIT:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Looper;
import com.name.framework.Game;
import com.name.framework.Graphics;
import com.name.framework.Image;
import com.name.framework.Input.TouchEvent;
import com.name.framework.Screen;
// Creates live game screen
public class GameScreen extends Screen {
enum GameState {
Running, Paused, GameOver
}
GameState state = GameState.Running;
// Instance variables
Random r = new Random();
int z = r.nextInt(16);
private int score = 0;
int count = 0;
private Runnable run;
public GameScreen(Game game) {
super(game);
Assets.paint = new Paint();
Assets.paint.setTextSize(30);
Assets.paint.setTextAlign(Paint.Align.LEFT);
Assets.paint.setAntiAlias(true);
Assets.paint.setColor(Color.BLACK);
}
// Check if touch coordinates fall in certain range
private boolean inBounds(TouchEvent event, int x, int y, int width, int height) {
if (event.x > x && event.x < x + width - 1 && event.y > y && event.y < y + height - 1)
return true;
else
return false;
}
#Override
public void update(float deltaTime) {
List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
// Call appropriate update method based on game state
if (state == GameState.Running)
updateRunning(touchEvents, deltaTime);
if (state == GameState.Paused)
updatePaused(touchEvents);
if (state == GameState.GameOver)
updateGameOver(touchEvents);
}
// Responds to in-game interaction
private void updateRunning(List<TouchEvent> touchEvents, float deltaTime) {
final Handler hand = new Handler();
run = new Runnable() {
#Override
public void run() {
if(count == 30) { //will end if count reach 30 which means 30 second
goToMenu();
}
else
{
count += 1; //add 1 every second
hand.postDelayed(run, 1000); //will call the runnable after 1 second
}
}
};
hand.postDelayed(run, 1000);
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = (TouchEvent) touchEvents.get(i);
if (event.type == TouchEvent.TOUCH_DOWN) {
switch(z) {
// Blue is correct
case 0:
case 1:
case 2:
case 3:
if (inBounds(event, 125, 150, 250, 100)) {
Assets.pop.play(0.8f);
score += 1;
z = r.nextInt(16); }
else if (inBounds(event, 425, 150, 250, 100)) {
Assets.bad.play(0.8f);
score -= 5;
z = r.nextInt(16); }
else if (inBounds(event, 125, 300, 250, 100)) {
Assets.bad.play(0.8f);
score -= 5;
z = r.nextInt(16); }
else if (inBounds(event, 425, 300, 250, 100)) {
Assets.bad.play(0.8f);
score -= 5;
z = r.nextInt(16); }
break;
// Green is correct
case 4:
case 5:
case 6:
case 7:
if (inBounds(event, 125, 150, 250, 100)) {
Assets.bad.play(0.8f);
score -= 5;
z = r.nextInt(16); }
else if (inBounds(event, 425, 150, 250, 100)) {
Assets.pop.play(0.8f);
score += 1;
z = r.nextInt(16); }
else if (inBounds(event, 125, 300, 250, 100)) {
Assets.bad.play(0.8f);
score -= 5;
z = r.nextInt(16); }
else if (inBounds(event, 425, 300, 250, 100)) {
Assets.bad.play(0.8f);
score -= 5;
z = r.nextInt(16); }
break;
// Red is correct
case 8:
case 9:
case 10:
case 11:
if (inBounds(event, 125, 150, 250, 100)) {
Assets.bad.play(0.8f);
score -= 5;
z = r.nextInt(16); }
else if (inBounds(event, 425, 150, 250, 100)) {
Assets.bad.play(0.8f);
score -= 5;
z = r.nextInt(16); }
else if (inBounds(event, 125, 300, 250, 100)) {
Assets.pop.play(0.8f);
score += 1;
z = r.nextInt(16); }
else if (inBounds(event, 425, 300, 250, 100)) {
Assets.bad.play(0.8f);
score -= 5;
z = r.nextInt(16); }
break;
// Yellow is correct
case 12:
case 13:
case 14:
case 15:
if (inBounds(event, 125, 150, 250, 100)) {
Assets.bad.play(0.8f);
score -= 5;
z = r.nextInt(16); }
else if (inBounds(event, 425, 150, 250, 100)) {
Assets.bad.play(0.8f);
score -= 5;
z = r.nextInt(16); }
else if (inBounds(event, 125, 300, 250, 100)) {
Assets.bad.play(0.8f);
score -= 5;
z = r.nextInt(16); }
else if (inBounds(event, 425, 300, 250, 100)) {
Assets.pop.play(0.8f);
score += 1;
z = r.nextInt(16); }
break;
}
// Pause button
if (inBounds(event, 750, 0, 50, 50)) {
Assets.pop.play(0.8f);
Assets.theme.pause();
state = GameState.Paused;
}
}
// Prevents score from becoming negative
if (score < 0) {
score = 0;
}
}
}
// Responds to pause menu interaction
private void updatePaused(List<TouchEvent> touchEvents) {
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if (event.type == TouchEvent.TOUCH_UP) {
// Resume button
if (inBounds(event, 125, 150, 250, 100)) {
Assets.pop.play(0.8f);
Assets.theme.play();
state = GameState.Running; }
// Restart button
else if (inBounds(event, 425, 150, 250, 100)) {
Assets.pop.play(0.8f);
Assets.theme.play();
nullify();
state = GameState.Running; }
// Mute button
else if (inBounds(event, 125, 300, 250, 100)) {
Assets.pop.play(0.8f);
}
// Menu button
else if (inBounds(event, 425, 300, 250, 100)) {
Assets.pop.play(0.8f);
//Assets.theme.seekBegin(); // not sure if I should do this
Assets.theme.play();
nullify();
goToMenu(); }
}
}
}
// Responds to game over interaction
private void updateGameOver(List<TouchEvent> touchEvents) {
}
#Override
public void paint(float deltaTime) {
Graphics g = game.getGraphics();
g.clearScreen(16777215);
g.drawImage(Assets.score, 20, 430);
g.drawImage(Assets.blue, 125, 150);
g.drawImage(Assets.green, 425, 150);
g.drawImage(Assets.red, 125, 300);
g.drawImage(Assets.yellow, 425, 300);
g.drawString(""+ score, 135, 465, Assets.paint);
//g.drawString(""+x, 750, 430, Assets.paint);
// Adds text to array and draws random one
ArrayList<Image> colors = new ArrayList<Image>();
colors.add(Assets.blueInBlue);
colors.add(Assets.blueInGreen);
colors.add(Assets.blueInRed);
colors.add(Assets.blueInYellow);
colors.add(Assets.greenInBlue);
colors.add(Assets.greenInGreen);
colors.add(Assets.greenInRed);
colors.add(Assets.greenInYellow);
colors.add(Assets.redInBlue);
colors.add(Assets.redInGreen);
colors.add(Assets.redInRed);
colors.add(Assets.redInYellow);
colors.add(Assets.yellowInBlue);
colors.add(Assets.yellowInGreen);
colors.add(Assets.yellowInRed);
colors.add(Assets.yellowInYellow);
if (state == GameState.Running) {
g.drawImage(colors.get(z), 0, 0);
}
// Calls the appropriate function to draw the UI based on game state
if (state == GameState.Running)
drawRunningUI();
if (state == GameState.Paused)
drawPausedUI();
if (state == GameState.GameOver)
drawGameOverUI();
}
// Draws in-game UI
private void drawRunningUI() {
Graphics g = game.getGraphics();
g.drawImage(Assets.pause, 750, 0);
}
// Draws pause menu UI
private void drawPausedUI() {
Graphics g = game.getGraphics();
g.drawARGB(155, 0, 0, 0);
g.drawImage(Assets.paused, 0, 0);
g.drawImage(Assets.resume, 125, 150);
g.drawImage(Assets.restart, 425, 150);
g.drawImage(Assets.mute, 125, 300);
g.drawImage(Assets.returnToMenu, 425, 300);
}
// Draws game over UI
private void drawGameOverUI() {
}
// Pause function
#Override
public void pause() {
if (state == GameState.Running)
state = GameState.Paused;
}
// Resume function
#Override
public void resume() {
if (state == GameState.Paused)
state = GameState.Running;
}
#Override
public void backButton() {
pause();
}
private void goToGameOver() {
game.setScreen(new MainMenuScreen(game));
}
// Resets timer and score
private void nullify() {
score = 0;
// Calls garbage collector to clean up memory
System.gc();
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
}
I would recommend handler for this even though you said that you've tried it, but i think you did not implement it correctly.
Here is the implementation and it work great on mine.
final Handler hand = new Handler();
run = new Runnable() {
#Override
public void run() {
if(count == 30) { //will end if count reach 30 which means 30 second
goToGameOver();
}
else
{
count += 1; //add 1 every second
hand.postDelayed(run, 1000); //will call the runnable after 1 second
}
}
};
hand.postDelayed(run, 1000);
Make sure that count and handler are global fields.