The issue in the game is that the player should only be able to change gravity when touching the ground or the ceiling, but occasionally, the player can do so while in the air. The `canSwitchGravity` variable was implemented to manage this behavior, but sometimes it doesn’t work as expected.
package src.objects;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.LinkedList;
import src.window.Handler;
import src.framework.GameObject;
import src.framework.ObjectId;
public class Player extends GameObject {
private float width=32 , height=64;
private float gravity = 0.1f;
private final float MAX_SPEED=10;
private Handler handler;
public Player(float x, float y, Handler handler, ObjectId id){
super(x, y, id);
this.handler=handler;
}
public void tick(LinkedList<GameObject> object) {
//Aggiorna la posizione del giocatore in base alla sua velocità.
x+=velX;
y+=velY;
if(gravityInverted){
velY+= -gravity; //inverti gravità --> sale
}else
velY+=gravity; //gravità normale --> scende
if(velY> MAX_SPEED){
velY=MAX_SPEED; //limito la velocità
} else if (velY < -MAX_SPEED) {
velY = -MAX_SPEED;
}
x+=2;
Collision(object);
}
private void Collision(LinkedList<GameObject> objects){
for(int i=0; i< handler.object.size(); i++){
GameObject tempObject= handler.object.get(i);
if(tempObject.getId() == ObjectId.Block){
if (getBoundsTop().intersects(tempObject.getBounds())) {
y=tempObject.getY() +32;
velY = 0;
canSwitchGravity=true;
}
if (getBounds().intersects(tempObject.getBounds())) { //intersects verifica se 2 rettangoli si intersecano
y=tempObject.getY() - height;
velY = 0;
canSwitchGravity=true;
}
//Right
if (getBoundsRight().intersects(tempObject.getBounds())) {
x=tempObject.getX() -32;
}
//left
if (getBoundsLeft().intersects(tempObject.getBounds())) {
x=tempObject.getX() +32;
}
}
}
}
public void render(Graphics g) {
g.setColor(Color.blue);
g.fillRect((int)x, (int) y,(int)width, (int)height);
/*Graphics2D g2d = (Graphics2D) g;
g.setColor(Color.red);
g2d.draw(getBounds());
g2d.draw(getBoundsTop());
g2d.draw(getBoundsRight());
g2d.draw(getBoundsLeft());
*/
}
//definisco i rettangoli di collisione in diverse direzioni (alto, basso, sinistra e destra) per il giocatore
public Rectangle getBounds() {
return new Rectangle((int)(x+(width/2)-(width/2)/2), (int) (y+(height/2)) ,(int)width/2, (int)height/2 );
}
public Rectangle getBoundsTop() {
return new Rectangle((int)(x+(width/2)-(width/2)/2), (int) y,(int)width/2, (int)height/2 );
}
public Rectangle getBoundsRight() {
return new Rectangle((int)(x+width-5), (int) y+5,(int) 5, (int)height-10 );
}
public Rectangle getBoundsLeft() {
return new Rectangle((int)x, (int) y+5,(int) 5, (int)height-10 );
}
}
package src.window;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.Random;
import src.framework.KeyInput;
import src.framework.ObjectId;
import src.objects.Block;
import src.objects.Player;
public class Game extends Canvas implements Runnable{
private boolean running = false;
private Thread thread;
public static int HEIGHT,WIDTH;
private BufferedImage level ;
Handler handler;
Camera cam;
Random rand = new Random();
public synchronized void start(){
if(running) //se è true il metodo ritorna immediatamente e non fa nulla (il gioco è già in esecuzione).
return;
running=true;
thread = new Thread(this); // crea un nuovo thread che eseguirà il codice del metodo run() della tua classe Game(this si riferisce a game poichè thread accetta oggetto runnable e game implemetna runnable).
thread.start(); //chiama il metodo run
}
private void init(){
WIDTH= getWidth();
HEIGHT = getHeight();
BufferImageLoader loader = new BufferImageLoader();
level= loader.loadImage("/src/res/level.png"); //loading level
handler = new Handler();
cam = new Camera(0,0);
LoadImageLevel(level);
this.addKeyListener(new KeyInput(handler));
}
public void run(){ //aggiungo ciclo di gioco
init();
this.requestFocus();
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000/amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int updates = 0;
int frames = 0;
while (running) {
long now = System.nanoTime();
delta += ( now - lastTime)/ ns;
lastTime = now ;
while (delta >=1) {
tick();
updates++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer > 1000){
timer+=1000;
System.out.println("FPS: " + frames + " TICKS: " + updates);
frames=0;
updates=0;
}
}
}
private void tick(){
handler.tick();
cam.tick();
}
private void render(){
BufferStrategy bs = this.getBufferStrategy();//Recupera la strategia di buffering corrente
if(bs== null){ //Se non esiste una strategia di buffering, ne crea una
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
Graphics2D g2d=(Graphics2D) g;
////////////////////////////
//Draw here
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
g2d.translate(cam.getX(), cam.getY());//begin of cam
//translate() sposta l'intera area di disegno in base alle coordinate della telecamera.
handler.render(g);
g2d.translate(-cam.getX(), -cam.getY());//end of cam
//Se non usassi g2d.translate(-cam.getX(), -cam.getY()), la traslazione si accumulerebbe ad ogni ciclo di rendering, ciò che disegnerei nei cicli successivi sarebbe ulteriormente spostato di una certa quantità rispetto alla posizione corrente
////////////////////////////
g.dispose();
bs.show();
}
private void LoadImageLevel( BufferedImage image){
int w = image.getWidth();
int h = image.getHeight();
System.out.println("width, height: " + w + " "+ h);
for(int xx =0; xx<h; xx++){
for(int yy=0; yy < w; yy++){
int pixel = image.getRGB(xx, yy);
Color pixelColor = new Color(pixel);
if( pixelColor.equals(Color.white)){
handler.addObject(new Block(xx*32, yy*32, ObjectId.Block));
}
if( pixelColor.equals(Color.blue)){
handler.addObject(new Player(xx*32, yy*32, handler,ObjectId.Player));
}
//moltiplico per 32 perchè 1 pixel rappresenta un blocco 32x32
}
}
}
public static void main(String[] args) {
new Window(800, 600, "prototype",new Game());
}
}
package src.framework;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import src.objects.Player;
import src.window.Handler;
public class KeyInput extends KeyAdapter{
Handler handler;
public KeyInput(Handler handler){
this.handler=handler;
}
public void keyPressed(KeyEvent e){
int key=e.getKeyCode();
for(int i =0 ; i<handler.object.size(); i++){
GameObject tempObject= handler.object.get(i);
if (tempObject.getId() == ObjectId.Player) {
if (key == KeyEvent.VK_SPACE && ((Player) tempObject).canSwitchGravity ) {
tempObject.setGravityInverted(!tempObject.isGravityInverted());
((Player) tempObject).canSwitchGravity = false;
}
}
}
if(key== KeyEvent.VK_ESCAPE){
System.exit(1);
}
}
}
package src.framework;
import java.util.LinkedList;
import java.awt.Graphics;
import java.awt.Rectangle;
public abstract class GameObject{
protected float x,y;
protected float velX=0,velY=0;
protected ObjectId id;
protected boolean gravityInverted=false;
protected boolean canSwitchGravity = false;
public GameObject(float x, float y, ObjectId id){
this.x = x;
this.y=y;
this.id = id;
}
public abstract void tick(LinkedList <GameObject> object);
public abstract void render(Graphics g);
public abstract Rectangle getBounds();
public float getX(){
return x;
}
public float getY(){
return y;
}
public void setX(float x){
this.x = x;
}
public void setY(float y){
this.y = y;
}
public float getVelX(){
return velX;
}
public float getVelY(){
return velY;
}
public void setVelX(float velX){
this.velX=velX;
}
public void setVelY(float velY){
this.velY=velY;
}
public boolean isGravityInverted(){
return gravityInverted;
}
public void setGravityInverted(boolean gravityInverted){
this.gravityInverted=gravityInverted;
}
public ObjectId getId(){
return id;
}
}
these are the principle classes need for this problem
It’s possible that the problem is due to collision detection: the game might be registering a collision even when the player is just grazing the block, leading to an unintended gravity switch. This could cause the gravity to change at unintended moments.
Ste Michelini is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1