Processing game: Gif images not respawning as intended - java

I am a diploma student making a game based on processing, it's a tower defense game where a heroine would be shooting arrows at zombies charging towards the castle. I have multiple issues with this.
The charger zombies do not respawn after being shot dead.
All of the charger zombies die together when I shot only one charger zombie.
Supposedly I wanted the zombies to spawn in waves repeatedly after a group of them has been shot down, and then I want the charger zombies to die individually, depending on the one I click on.
Here's my source code:
import processing.opengl.*; // transparency
import gifAnimation.*; // after add gifAnimation library
import ddf.minim.*; // importing music
PImage backgroundImg;
PImage animation;
int counter;
//settings
int score = 50, totalScore = 0;
int titleX = 200, titleY = 200;
boolean shotsFired = false;
PFont scorePoints, castleHealthPoints, font; //font for startingScreen
int chargerKilled;
//Charger class
int maxChargerOnScreen;
Charger[] chargerArr; //chargerArray undefined
int chargerIndex;
final int numCharger = 300;
ArrayList<Charger> onScreen = new ArrayList<Charger>();
boolean chargerReachedTarget = false, chargerShot = false, chargerDive = true;
Gif chargerCharge, chargerAttack, chargerDied, shootingStance;
int chargerMoveX = 800, chargerMoveY = 450;
// CastleWallHealth
int castleHealth = 1000;
// audio
Minim minim;
AudioPlayer song;
AudioSnippet arrowShoot;
//-------------------------------Codes start here --------------------------------------------------//
void setup() {
//ipad mini size
// frameRate(10);
frameRate(60);
size(800, 600);
smooth();
minim = new Minim(this);
// song = minim.loadFile("InGameSoundtrack.mp3");
// song.play();
arrowShoot = minim.loadSnippet("arrowSound1.wav");
backgroundImg = loadImage("GameBackground.jpg");
backgroundImg.resize(800, 600);
chargerCharge = new Gif(this, "ChargerCharge.gif");
chargerAttack = new Gif(this, "ChargerAttack.gif");
chargerDied = new Gif(this, "ChargerDie.gif");
gargoyleFly = new Gif(this, "GargoyleFly.gif");
gargoyleAttack = new Gif(this, "GargoyleAttack.gif");
shootingStance = new Gif(this, "ShootingGif.gif");
scorePoints = createFont("Arial", 16, true);
castleHealthPoints = createFont("Arial", 16, true);
// loopingGif.play() plays the animation without loop
// must make charger
chargerCharge.play();
chargerAttack.play();
chargerDied.play();
resetGames(); // starts with respawning 5 charges
}
void draw() {
// backgroud
background(backgroundImg);
image(shootingStance, 120,200);
// scores and health
textFont(scorePoints, 15);
fill(0);
text("Score: " + totalScore, 100, 100);
displayCastleHealth();
//*********************************************charger settings code********************************************************************
// If there's no more zombies. prompt reset (screen no zombies) , index from 0 add till 300 then game won
if (onScreen.size() == 0 && chargerIndex == numCharger) {
println("Game won! :)");
// gameWon = true;
}
// while onScreen charger less than 5 only and chargerIndex havent reach 300 it will only respawn
while (onScreen.size () < maxChargerOnScreen && chargerIndex <= numCharger - 1) {
if (chargerIndex < chargerArr.length) { // <--- this is the problem chargerArrayLength
Charger chargerMobs = chargerArr[chargerIndex];
// starts from chargerArray[0] to chargerArray[300]
onScreen.add(chargerMobs);
chargerIndex++;
// chargerIndex keeps looping why?
// println("ADDED ZOMBIE TO ONSCREEN Zombs on screen: " + onScreen.size());
}
}
// Adjusts maxZombOnScreen based off the current index Difficulties?
if (chargerIndex == 10)
maxChargerOnScreen++;
else if (chargerIndex == 50)
maxChargerOnScreen++;
else if (chargerIndex == 100)
maxChargerOnScreen += 2;
else if (chargerIndex == 150)
maxChargerOnScreen += 2;
else if (chargerIndex == 190)
maxChargerOnScreen += 3;
else if (chargerIndex == 250)
maxChargerOnScreen += 3;
else if (chargerIndex == 260)
maxChargerOnScreen += 3;
else if (chargerIndex == 270)
maxChargerOnScreen += 5;
// removes dead zombies, living zombies act normally
for(int i = 0; i < onScreen.size(); i++) {
Charger c = onScreen.get(i);
// add money when a zombie is dead
// if (c.getHealth() <= 0)
if (chargerShot==true) {
c.chargerDying();
onScreen.remove(i);
chargerKilled++;
i--;
} else {
c.act(); ///it should just act
// c.displayHealth(); // if gt time only do
// }
}
}
// creating list of predetermined zombies and their characteristics
println("chargerIndex: " + chargerIndex); // debug
println("onScreenSize: " + onScreen.size());
// println("ChargerArray: " + chargerArray.length); chargerArray point null?
// cursor
if (mouseY > height - 500) {
noFill();
stroke(255, 0, 0);
ellipse(mouseX, mouseY, 35, 35);
line(mouseX - 25, mouseY, mouseX + 25, mouseY);
line(mouseX, mouseY - 25, mouseX, mouseY + 25);
}
}
void resetGames() {
// resetting variables
chargerIndex = 0;
maxChargerOnScreen = 5;
chargerKilled = 0;
createNewCharger();
}
void createNewCharger() {
Charger[] temp = new Charger[numCharger];
for (int i = 0; i < numCharger; i++)
temp[i] = new Charger((int) random(800, 1200), chargerMoveY);
chargerArr = temp;
}
//____________________________________________________________________________________________________________-
class Charger {
private int chargerMoveX, chargerMoveY;
Gif chargerGif; // by default
// chargerGif will change based on input (either it reaches the castle or its shot)
// no constructor
Charger() {
chargerMoveX = 0;
chargerMoveY = 450;
}
// overloaded constructor
Charger(int cMoveX,int cMoveY) {
chargerMoveX = cMoveX;
chargerMoveY = cMoveY;
}
void act() { // use
// if reached castle it wont move
if (chargerMoveX <= 180) {
// remove gif images
chargerDive = false;
chargerReachedTarget = true;
}
// if not shot or reached castle it will move
if (chargerDive == true) {
chargerGif = chargerCharge;
image(chargerGif, chargerMoveX, chargerMoveY);
chargerMoveX -= 2;
}
// if reached castle perform attack animation
if (chargerReachedTarget == true) {
chargerGif = chargerAttack;
image(chargerGif, chargerMoveX - 80, chargerMoveY - 120);
}
if (mousePressed &&
mouseX < chargerMoveX + 180
&& mouseX > chargerMoveX
&& mouseY < chargerMoveY + 120
&& mouseY > chargerMoveY) {
// score board
totalScore = totalScore + score ;
float r = random(50);
println(r);
chargerShot = true;
chargerDive = false;
}
}
void chargerDying() {
chargerReachedTarget = false;
chargerGif = chargerDied;
image(chargerGif, chargerMoveX, chargerMoveY);
}
}
void displayCastleHealth() {
if (castleHealth <= 0) {
fill(250, 70, 0);
textFont(castleHealthPoints, 20);
text("HP: 0", 100, 50);
} else {
fill(250, 70, 0);
textFont(castleHealthPoints, 20);
text("HP: " + castleHealth, 100, 50);
}
}
void mousePressed() {
strokeWeight(2);
arrowShoot.rewind();
arrowShoot.play();
for (int i = 0 ; i < 3; i++)
shootingStance.play();
shotsFired = true;
}
void mouseReleased() {
strokeWeight(1);
if (shotsFired == true)
shootingStance.pause();
}
public void stop() {
arrowShoot.close();
}
Majority of the problems from the charger came from here:
if (onScreen.size() == 0 && chargerIndex == numCharger) {
println("Game won! :)");
// gameWon = true;
}
// while onScreen charger less than 5 only and chargerIndex havent reach 300 it will only respawn
while (onScreen.size () < maxChargerOnScreen && chargerIndex <= numCharger - 1) {
if (chargerIndex < chargerArr.length) { // <--- this is the problem chargerArrayLength
Charger chargerMobs = chargerArr[chargerIndex];
// starts from chargerArray[0] to chargerArray[300]
onScreen.add(chargerMobs);
chargerIndex++;
// chargerIndex keeps looping why?
// println("ADDED ZOMBIE TO ONSCREEN Zombs on screen: " + onScreen.size());
}
}
// Adjusts maxZombOnScreen based off the current index Difficulties?
if (chargerIndex == 10)
maxChargerOnScreen++;
else if (chargerIndex == 50)
maxChargerOnScreen++;
else if (chargerIndex == 100)
maxChargerOnScreen += 2;
else if (chargerIndex == 150)
maxChargerOnScreen += 2;
else if (chargerIndex == 190)
maxChargerOnScreen += 3;
else if (chargerIndex == 250)
maxChargerOnScreen += 3;
else if (chargerIndex == 260)
maxChargerOnScreen += 3;
else if (chargerIndex == 270)
maxChargerOnScreen += 5;
// removes dead zombies, living zombies act normally
for(int i = 0; i < onScreen.size(); i++) {
Charger c = onScreen.get(i);
// add money when a zombie is dead
// if (c.getHealth() <= 0)
if (chargerShot==true) {
c.chargerDying();
onScreen.remove(i);
chargerKilled++;
i--;
} else {
c.act(); ///it should just act
// c.displayHealth(); // if gt time only do
// }
}
}
Evaluation and criticism is appreciated.

There are several issues with the code, but for now, I'll ignore the parts that are somewhat "not clean" or "not elegant", and focus on the main problem that was the reason for the question:
The state of all Chargers instances was the same. The fields
boolean chargerReachedTarget = false, chargerShot = false, chargerDive = true;
have been defined globally. Just by moving this line (that is, these 3 fields) into the Charger class, and changing the line
if (chargerShot==true) {
to
if (c.chargerShot==true) {
the game already seemed to be much closer to what you presumably have been looking for. After this modification, it was possible to shoot individual opponents, and new opponents kept coming after the old ones had disappeared.
Again: The code is not really nicely structured, and there are many possible minor improvements. For example, something like if (c.chargerShot==true) { ... } should better be if (charger.isShot()) { ... }. But I'm not so familiar with processing and its best practices, so I'm not sure how the "best" solution would look like in a global sense...

Related

Why are there two player speeds in my game?

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.

Intersect function stops working after the first intersect

im making a game, but i ran into a problem while working with the function "intersect".
the senario looks like this; i've made a game where the player is a rectangle were the objective is to kill the enemy rectangle. The enemy "boss" rectangle has two "simulations" that simulate a movement and an attack these simulations are driven by vectors. The movement is horizantally back and forth and the attack is in a vertical maner, a charge type of deal. The boss also has a rectangular target area where if itersected the "boss" will charge across the screen.
now the problem comes when i tried to make it so that if the player intersects with the rectangular target area the "boss" will attack/charge. The boss attack/charge the first time the player intersects but not after that. I want the boss to follow the same pantern, is that he should only be able to go from side to side horizantaly and if Target area intersected; attack/charge verticaly.
( i will include some code bellow. sorry if my english is bad. )
first comes the main:
boss b;
Character C;
void setup(){
C = new Character();
b = new boss();
}
void draw(){
if (play) {
b.simulate(); //horizantal movement
}
if (b.start) {
b.sim(); //boss vertical attack
}
if (b.intersects(C)){
play = false;
b.start = true;
}
C.character(); //player
b.bounce(); //makes it bounce if horizantal. and stop if vertical
b.Display(); //boss
b.display(); //boss target area
}
Next comes the boss:
class boss {
int x = 10 ;
int y = 10 ;
boolean start = false;
int RW = 50;
int RH = 700;
boolean up = false;
boolean down = true;
boss() {
Location = new PVector( x+25, y ); //vector for the location of the boss
Velocity = new PVector( 5, 0 ); // vector for horizaltal movement
speed = new PVector( 0, 10 ); // vector for vertical down movement
speed2 = new PVector(0, -10); // vector for vertical up movement
}
void bounce() {
if ((Location.x == width) ||(Location.x == 0)) { //horizantal movement bounce on screen edge
Velocity.x = Velocity.x * -1;
}
if ((Location.y == 650) || (Location.y == 0)) {
start = false; //makes boss stop if reaches botton or top of the screen
play = true;
if (Location.y == 650) {
RH = -700;
up = true;
down = false; //specificly if it reaches top of screen
}
if (Location.y == 0) {
RH = 700;
down = true; //specificly if it reaches bottom of screen
up = false;
}
}
}
void simulate() {
Location.add(Velocity); //simulates horizantal movement
}
void sim() {
if (down) {
Location.add(speed); //simulates up and down attacking movemnet
}
if (up) {
Location.add(speed2);
}
}
boolean intersects(Character C) {
return Location.x < C.x + C.w && C.x < Location.x + RW &&
Location.y < C.y + C.h && C.y < Location.y + RH; //intersect between player and boss targeting area
}
void Display() {
rect( Location.x, Location.y, 50, 50 ); //boss
}
void display() {
rect( Location.x, Location.y+50, RW, RH ); //boss targeting area
}
}
if anything is unclear i will gladly clear up any confusion. :)
Thanks for sharing the code. It made it much easier.
When I comment this piece (not the if-condition the reset of start after the if)
if ((Location.y == 650) || (Location.y == 0)) {
// start = false;
then the boss starts going back up top and still calls intersects the Character when the co-ordinates match. However, post this the boss keeps bouncing up and down.
There is surely more work to be done on this to take account of the bullets fired and the hits to boss.
Hope this helps. :) It was fun debugging this code. I had never used PDE before this.
ok, here is the "edit"..
Now,
Good News: I can make it go in both directions only when it intersects
Bad News: It keeps going to the other side as long as it is intersecting. So if the Character is stationary then boss keeps intersecting and passing to the other side at least 8-10 times in the current speed.
Anyways, here is the summary. I added and isAttacking flag that tells the program to not stop the boss from crossing over if it has reached the bottom of the frame. The other thing I changed was the intersection condition. Now it just checks for intersection on the X-Axis. If you must compare intersection on the Y-Axis too then intersects is where you need to change & test.
After the long explanation :P Here is the code. Hope this is better.
Main
boss b;
Character C;
Inventory I;
Bullet B;
int previousKey = 0;
int lastKey;
int lastKeyCode;
void setup() {
C = new Character();
b = new boss();
I = new Inventory();
background(128, 128, 128);
size( 700, 700 );
strokeWeight( 10 );
frameRate( 30 );
}
void keyPressed() {
if (key == CODED) {
previousKey = keyCode;
if (keyCode == UP) {
C.MoveUP();
}
if (keyCode == LEFT) {
C.MoveLEFT();
}
if (keyCode == DOWN) {
C.MoveDOWN();
}
if (keyCode == RIGHT) {
C.MoveRIGHT();
}
}
if (key == 'w' || key == 'W') {
attack();
}
if ( key == 'q' || key == 'Q' ) {
if (I.Shoot == true) {
B = new Bullet(C.x, C.y);
this.Shoot();
}
} else if (key == 'e' || key == 'E') {
I.changePop();
}
if (keyPressed) {
if (key == 'a' || key == 'A') {
//play = false;
//b.start = true;
}
}
}
void attack() {
if (I.Attack == true) {
if (previousKey == UP) {
C.AttackUP();
}
if (previousKey == LEFT) {
C.AttackLEFT();
}
if (previousKey == DOWN) {
C.AttackDOWN();
}
if (previousKey == RIGHT) {
C.AttackRIGHT();
}
}
}
void Shoot() {
if (I.Shoot == true) {
if (previousKey == UP) {
B.ShootUP();
}
if (previousKey == LEFT) {
B.ShootLEFT();
}
if (previousKey == DOWN) {
B.ShootDOWN();
}
if (previousKey == RIGHT) {
B.ShootRIGHT();
}
}
}
boolean play = true;
void keyReleased() {
lastKey = 0;
lastKeyCode = 0;
}
void draw() {
background(128, 128, 128);
if (play) {
b.simulate();//side to side
}
if (b.start) {
b.sim(); //boss rush
}
if (b.intersects(C)) {
b.isAttacking = true;
play = false;
b.start = true;
} else {
b.isAttacking= false;
}
C.character();
b.bounce();
b.Display();//boss
b.display();//rush area
C.HPbar();
I.popUp();
if ( key == 'q' || key == 'Q' ) {
if (I.Shoot == true) {
B.bullet();
B.Simulate();
}
}
}
Enemies or Boss
class boss {
PVector Location;
PVector Velocity;
PVector speed;
PVector speed2;
int x = 10 ;
int y = 10 ;
boolean start = false;
int RW = 50;
int RH = 700;
boolean up = false;
boolean down = true;
boolean isAttacking = false;
boss() {
Location = new PVector( x+25, y );
Velocity = new PVector( 5, 0 );
speed = new PVector( 0, 10 );
speed2 = new PVector(0, -10);
}
void bounce() {
if ((Location.x == width) ||(Location.x == 0)) {
Velocity.x = Velocity.x * -1;
}
if ((Location.y == 650) || (Location.y == 0)) {
if (!isAttacking) {
start = false;
}
play = true;
if (Location.y == 650) {
RH = -700;
up = true;
down = false;
}
if (Location.y == 0) {
RH = 700;
down = true;
up = false;
}
}
}
void simulate() {
Location.add(Velocity);
}
void sim() {
//print("\n In Sim UP: [" + up + "] Down: [" + down + "] Location [" + Location + "]");
if (down) {
Location.add(speed);
}
if (up) {
Location.add(speed2);
}
}
boolean intersects(Character C) {
//print ("\nUP: [" + up + "] Down: [" + down + "] X: [" + (Location.x < (C.x + C.w) && (Location.x + RW) > C.x)
//+ "] Y: [" + (Location.y < (C.y + C.h) && (Location.y + RH) > C.y) + "]");
return Location.x < (C.x + C.w) && (Location.x + RW) > C.x;
//&&
// Location.y < (C.y + C.h) && (Location.y + RH) > C.y ;
}
void Display() {
pushStyle();
stroke(0);
fill(255, 0, 0);
rect( Location.x, Location.y, 50, 50 );
popStyle();
}
void display() {
pushStyle();
stroke(0);
strokeWeight(0);
fill(255, 0, 0, 20);
rect( Location.x, Location.y+50, RW, RH );
popStyle();
}
}

Pong game is running too fast with FPS counter

I have a Pong game with an FPS counter but I have a few problems. I want the FPS counter to NOT be limited at 60 FPS, I want the FPS counter to go as high as it can.
The FPS is currently working but the problem is that the game is running REALLY fast, I want the game to always run at a speed that is playable. I tried adding a timer for 5 ms but that caused the FPS counter to not work properly.
I want the FPS counter to NOT be limited at 60 FPS but at the same time use some sort of timer. Here is my code:
package Game;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class Main extends JPanel implements KeyListener, ActionListener{
// Lite variabler
JFrame frame;
int windowWidth, windowHeight;
Point bollXY;
int screenWidth, screenHeight;
Image bildPaddel;
Image bildBollen;
int paddelY;
int paddel2Y;
boolean paddelUp, paddelDown;
Random rand;
int score, score2;
boolean bollUp, bollRight, changeDirection;
int fruktDistansRand;
long time;
int fps, newfps;
int fpsTimesCounter;
// Konstruktor
public Main(){
// Definera variabler
frame = new JFrame();
bildPaddel = new ImageIcon("src/images/Player.png").getImage();
bildBollen = new ImageIcon("src/images/Pong.png").getImage();
bollXY = new Point(673, 352);
paddelY = 312;
paddel2Y = 312;
paddelUp = false;
rand = new Random();
score = 0;
score2 = 0;
bollUp = false;
bollRight = false;
changeDirection = false;
fruktDistansRand = 0;
time = System.currentTimeMillis();
fps = 0;
newfps = 0;
fpsTimesCounter = 0;
// Lyssnare
frame.addKeyListener(this);
// Bygga fönstret
frame.add(this);
// Obligatoriska egenskaper
frame.setTitle("Pong");
frame.setSize(1366, 724); // Eftersom spelet inte ska vara helt i fullskärm sätts fönstret på 1366x724 så att aktivitetsfältet syns
frame.setVisible(true);
frame.setLocationRelativeTo(null); // Centrerar fönstret
frame.setResizable(false);
this.setBackground(Color.BLACK);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
bollUp = true;
bollRight = true;
changeDirection = false;
bollXY = new Point();
frame.add(this);
}
// Metoder
public static void main(String[] args) {
new Main();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(bildBollen, bollXY.x, bollXY.y, null);
g.drawImage(bildPaddel, 50, paddelY, null);
g.drawImage(bildPaddel, 1300, paddel2Y, null);
g.setFont(new Font("Arial", Font.BOLD, 100));
g.setColor(Color.WHITE);
g.drawString(score2 + "", 1002, 100);
g.drawString(score + "", 314, 100);
if(System.currentTimeMillis() - time >= 1000){
time = System.currentTimeMillis();
fps = newfps;
newfps = 0;
}
else{
newfps++;
}
g.setFont(new Font("Arial", Font.BOLD, 25));
g.drawString(fps + "", 5, 22);
update();
}
public void AI(){
fruktDistansRand = rand.nextInt(200) + 950;
if(bollXY.x > fruktDistansRand && bollXY.x < 1380 && bollRight && paddel2Y > 0 && paddel2Y < 596){
if(paddel2Y + 50 < bollXY.y){
paddel2Y = paddel2Y + 3;
}
else{
paddel2Y = paddel2Y - 3;
}
if(paddel2Y <= 0){
paddel2Y = paddel2Y + 3;
}
if(paddel2Y >= 596){
paddel2Y = paddel2Y - 3;
}
}
}
public void ifUp(){
if(bollUp){
if(changeDirection){
if(bollXY.y < 0){
bollUp = false;
}
else{
bollXY.y = bollXY.y - 3;
}
}
else{
if(bollXY.y < 0){
bollUp = false;
}
else{
bollXY.y = bollXY.y - 3;
}
}
}
else{
if(changeDirection){
if(bollXY.y > 675){
bollUp = true;
}
else{
bollXY.y = bollXY.y + 3;
}
}
else{
if(bollXY.y > 675){
bollUp = true;
}
else{
bollXY.y = bollXY.y + 3;
}
}
}
}
public void update(){
if(paddelUp){
if(paddelY > 0){
paddelY = paddelY - 3;
}
}
if(paddelDown){
if(paddelY < 596){
paddelY = paddelY + 3;
}
}
if(bollRight){
if(bollXY.x > 1290 && bollXY.x < 1300 && bollXY.y < paddel2Y + 100 && bollXY.y > paddel2Y-20){
if(!bollUp && bollXY.y < paddel2Y){
changeDirection = true;
bollUp = true;
}
else if(bollUp && bollXY.y > paddel2Y + 80){
changeDirection = true;
bollUp = false;
}
bollRight = false;
}
else if(bollXY.x > 1600){
score++;
bollXY.y = rand.nextInt(690);
bollXY.x = 678;
}
else
bollXY.x = bollXY.x + 3;
ifUp();
}
else{
if(bollXY.x > 50 && bollXY.x < 60 &&bollXY.y < paddelY + 100 && bollXY.y > paddelY-20){
if(!bollUp && bollXY.y < paddelY){
changeDirection = true;
bollUp = true;
}
else if(bollUp && bollXY.y > paddelY + 80){
changeDirection = true;
bollUp = false;
}
bollRight = true;
}
else if(bollXY.x < -244){
score2++;
bollXY.x = 678;
bollXY.y = rand.nextInt(596);
}
else
bollXY.x = bollXY.x - 3;
ifUp();
}
AI();
repaint();
}
#Override
public void actionPerformed(ActionEvent e) {
update();
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_W || e.getKeyCode() == KeyEvent.VK_UP){
paddelUp = true;
}
if(e.getKeyCode() == KeyEvent.VK_S || e.getKeyCode() == KeyEvent.VK_DOWN){
paddelDown = true;
}
}
#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_W || e.getKeyCode() == KeyEvent.VK_UP){
paddelUp = false;
}
if(e.getKeyCode() == KeyEvent.VK_S || e.getKeyCode() == KeyEvent.VK_DOWN){
paddelDown = false;
}
}
#Override
public void keyTyped(KeyEvent e) {
}
}
Your game is running really fast, because you use a static increment in each cpu cycle. If you run this program on an slow cpu, your game will run slower. If you run it with a fast cpu your game will run faster.
cpu 1: 100 cycles per second: your ball will move 300 units per second.
cpu 2: 2000 cycles per second: your ball will move 6000 units per second.
When you capped your game at 60 fps, you avoided that issue, because the update will only happen 60 times per second and not 100 or 2000 times.
Another option is to involve time.
This means you measure the time since the last frame and use it as an multiplicator. The faster your cpu runs the lower your time between frames will be. Your ball will move acording to you time. If your your cpu is slower the time between your frames increases and the ball will move further.
float delta = // time between your frames
pulic void update(float delta){
...
bollXY.y -= delta * 3;
Alternatively a great article for game loops: https://gafferongames.com/post/fix_your_timestep/

checking if 2 rectangles WILL overlap

I have been trying to do player intersection with a small project i'm doing, and I can't seem to make it work. I got the Intersection to work with the player and the wall, but it's very buggy, by buggy I mean, it draws the player in the wall then moves him back instantly. (Check Gyazo for gif of this). I'm pretty sure the problem is that it only checks if the player is in the wall, and not WILL be in the wall, but I can't seem to figure out how to check this. This is what I have so far:
public void intersectsBox2(Rectangle r, Rectangle r2) {
P1 = new Point((int) r.getMinX(), (int) r.getMinY());
P2 = new Point((int) r.getMaxX(), (int) r.getMaxY());
P3 = new Point((int) r2.getMinX(), (int) r2.getMinY());
P4 = new Point((int) r2.getMaxX(), (int) r2.getMaxY());
if ((P2.y < P3.y || P1.y > P4.y || P2.x < P3.x || P1.x > P4.x)
&& !intersectsBox(playerRectangle(), noWalls[0])) {
isInsideWalls = true;
}
}
// Gets the players rectangle
public Rectangle playerRectangle() {
return new Rectangle(9 + dx, 23 + dy, 54, 90);
}
This is to make the player Move:
public void playerMovement() {
if (isInsideWalls) {
System.out.println("YOU ARE IN THE BOX!");
if (animation == down) {
dy -= moveSpeed;
isInsideWalls = false;
} else if (animation == up) {
dy += moveSpeed;
isInsideWalls = false;
} else if (animation == left) {
dx += moveSpeed;
isInsideWalls = false;
} else if (animation == right) {
dx -= moveSpeed;
isInsideWalls = false;
}
} else {
// Moves the player
if (moving == downMove) {
dy += moveSpeed;
moving = 0;
} else if (moving == upMove) {
dy -= moveSpeed;
moving = 0;
} else if (moving == leftMove) {
dx -= moveSpeed;
moving = 0;
} else if (moving == rightMove) {
dx += moveSpeed;
moving = 0;
}
}
This is to check for the intersection:
//Checks for intersection
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
intersectsBox2(walls[i][j], playerRectangle());
}
}
Not really sure if this is needed but heres the full Game.java if you need to see this: http://pastebin.com/GrDy689d
Also here is the Gif of the problem: http://i.gyazo.com/1f31f739897af78f81e61cf22ac772db.mp4
P.S: It's on purpose I can only go into 1 box at the moment for testing purposes.
You could move the player, then check to see if it is in a wall and, if it is, undo the move (or better, calculate a new location as the result of a move, check it, and if it is good, only then move the player there). Note that this assumes a single move can't put you all the way on the other side of a wall, but then it looks like your code does, too.

Collision bug in a 2D platform game

I'm new to java, and game programming and I'm starting my first big project which is a 2D platform puzzle game.
This is my player movement code
if (speedX > 0 && centerX <= 400){
centerX += speedX;
}
if (speedX < 0 && centerX >= 400){
centerX += speedX;
}
if (speedX > 0 && centerX >= 400){
bg1.setSpeedX(-MOVESPEED);
bg2.setSpeedX(-MOVESPEED);
}
if (speedX < 0 && centerX <= 400){
bg1.setSpeedX(MOVESPEED);
bg2.setSpeedX(MOVESPEED);
}
if (speedX == 0){
bg1.setSpeedX(0);
bg2.setSpeedX(0);
}
if(movingRight == true && movingLeft == true ){
bg1.setSpeedX(0);
bg2.setSpeedX(0);
}
// Handles Jumping
if (jumped == true) {
speedY += 1;
}
// Prevents going beyond X coordinate of 0
if (centerX + speedX <= 60) {
centerX = 61;
}
rect.setRect(centerX - 47, centerY - 65, 32, 87);
centerY += speedY;
}
public void moveRight() {
speedX = MOVESPEED;
}
public void moveLeft() {
speedX = -MOVESPEED;
}
public void stopRight() {
movingRight = false;
stop();
}
public void stopLeft() {
movingLeft = false;
stop();
}
private void stop() {
if (movingRight == false && movingLeft == false) {
speedX = 0;
}
if (movingRight == false && movingLeft == true) {
moveLeft();
}
if (movingRight == true && movingLeft == false) {
moveRight();
}
}
public void jump() {
if (jumped == false) {
speedY = JUMPSPEED;
jumped = true;
}
}
and this is the collision code
public void checkCollision(Rectangle rect){
if (rect.intersects(r)){
if(Player.movingRight){
Player.centerX = tileX + 11;
Player.speedX =0;
}
if(Player.movingLeft){
Player.centerX = tileX + 89;
Player.speedX = 0;
}
if(Player.speedY > 0){
Player.centerY = tileY - 25;
Player.speedY = 0;
Player.jumped = false;
}
}
}
There are two problems.The first one is that if I press one of the movement keys when landing the character "teleports" to the right or left.
I know this happens because I programmed it that if the character intersects with the ground while movingRight or movingLeft are true he moves right or left.(I made it this way so the horizonal collision will work) and I cant think of any other way to do it or how to fix it.
The second problem is that if the character moves of a platfrom he does not fall down.
I tryed to fix it by adding to the collision method
else{
speedY += 1;
}
But it made the character disappear for some reason.
Thanks a lot!
This code was originally written in C++ for a 3D platformer. I rewrote it, but there might be some bugs. I can draw a picture later if it's difficult to understand.
public void checkCollision(Rectangle rect){
if(player.intersects(rect)) {
//the rectangles intersect, time to move the player out of the block
if(rect.y+rect.height >= player.y && rect.y+rect.height-0.7f < player.y) { //if the player is at most 0.7 units (you should change this!) below top side
player.y = rect.y+rect.height; //set player to stand on top
speed.y = 0f; //stop the movement
onGround = true;
} else if(rect.y+rect.height > player.y && rect.y < player.y+player.height) { //if the playeer is on the side, but not below
float xEscMinus = (float)Math.abs((rect.x+rect.width)-player.x); //find the distance to the side
float xEscPlus = (float)Math.abs(rect.x-(player.x+player.width));
if(xEscMinus<xEscPlus) {
player.x = rect.x+rect.width;
} else {
player.x = rect.x-player.width;
}
}
}
}

Categories