即使玩家跌倒,也会改变重力

问题描述 投票:0回答:1

我尝试重玩“Gravity Guys”游戏,在这个游戏中玩家只有在接触表面时才能改变重力。问题是它允许我在空气中改变重力。尝试给你举个例子来解释这个问题。想象一下玩家沿着方块行走,方块是半高的,完成的方块,如果我不按空格键改变重力,重力的玩家开始下落,但此时变量布尔值canswitchgravity设置为true,因为它之前在方块上行走时被激活,然后玩家可以跳跃,我不想要这个

public class Player extends GameObject {

    private float width=32 , height=64;

    private float gravity = 0.1f; //il suffisso f serve per indicare che è float
    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(ArrayList<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+=3;
        Collision(object);

    }

    private void Collision(ArrayList<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.getBoundsBot())) {
                    y=tempObject.getY() +32;
                    velY = 0;
                    canSwitchGravity=true;
                }

                if (getBoundsBot().intersects(tempObject.getBoundsTop())) { //intersects verifica se 2 rettangoli si intersecano
                    y=tempObject.getY() - height;
                    velY = 0;
                    canSwitchGravity=true;
                    
                }
                
                //Right
                if (getBounds().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);
    }


    //definisco i rettangoli di collisione in diverse direzioni (alto, basso, sinistra e destra) per il giocatore
    public Rectangle getBoundsBot() {

        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 getBounds() {//right

        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 );
    }
}

public class Game extends Canvas implements Runnable{
    
    private boolean running = false;
    private Thread thread;
    public static int HEIGHT,WIDTH;
    private Menu menu;

    public State gameState = State.Menu;
    public int score = 0;


    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();

        handler = new Handler();

        cam = new Camera(0,0);

        menu = new Menu(this, handler, cam);

        this.addKeyListener(new KeyInput(handler));
        this.addMouseListener(menu);
    }



    public void run(){ //aggiungo ciclo di gioco
        init();
        this.requestFocus(); // Garantisce che la finestra di gioco riceva il focus per permettere l'interazione dell'utente tramite tastiera e mouse con la finestra di gioco.
        long lastTime = System.nanoTime();
        double amountOfTicks = 60.0; //il gioco aggiorna la sua logica 60 volte al secondo
        double ns = 1000000000/amountOfTicks; // è il numero di nanosecondi che devono passare tra un tick e l'altro per ottenere esattamente amountOfTicks tick al secondo
        double delta = 0; //delta è essenziale per mantenere il gioco aggiornato a un ritmo costante di 60 volte al secondo
        long timer = System.currentTimeMillis();
        int updates = 0;
        int frames = 0;
        while (running) {
            long now = System.nanoTime();
            delta += ( now - lastTime)/ ns; // tiene traccia del tempo trascorso tra due esecuzioni del ciclo, per assicurarsi che gli aggiornamenti logici (tick) avvengano esattamente a 60
            lastTime = now ; //now - lastTime calcola quanto tempo è passato dall'ultima iterazione del ciclo
            while (delta >=1) { //Questo valore viene diviso per ns (cioè il tempo tra un tick e l'altro), per ottenere un valore che rappresenta quante frazioni di tick sono trascorse
                tick();
                updates++;
                delta--;
            }
            render();
            frames++;

            if(System.currentTimeMillis() - timer > 1000){
                timer+=1000;
                System.out.println("FPS: " + frames + " TICKS: " + updates);
                frames=0;
                updates=0;
            }
        }
    }
    //metodo che è responsabile dell'aggiornamento della logica del gioco (es. movimento dei personaggi, calcolo delle collisioni, ecc.)
    private void tick(){
        handler.tick();

        if (gameState == State.Game) {
            cam.tick();    
            score ++;
            
             for (int i = 0; i < handler.object.size(); i++) {
                GameObject tempObject = handler.object.get(i);

                if (tempObject.getId() == ObjectId.Player) {
                    Player player = (Player) tempObject; // Ottieni l'istanza del player
                    // Controlla se il player è fuori dallo schermo
                    if (player.getY() > (cam.getY() + Game.HEIGHT+64) || player.getY() < cam.getY()-64 || player.getX() < (-1 *cam.getX()-32) ) {
                        gameState = State.End;
                    }
                }   
            }      

        } else if (gameState == State.Menu || gameState == State.End) {
            menu.tick();
        }
            
        
    }

    //metodo per disegnare sullo schermo usando una strategia di buffering per migliorare la fluidità e ridurre lo sfarfallio.
    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;//trasformo g in g2d perchè graphics2d fornisce funzioni + avanzate come la traslazione
        ////////////////////////////
        
        //Draw here
        g.setColor(Color.black);
        g.fillRect(0, 0, getWidth(), getHeight());

        if (gameState == State.Game) {

            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);
            g.drawString("Score: "+ score, (int)(-cam.getX()+64),(int) (-cam.getY()+32));

            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
            

        }else if (gameState == State.Menu || gameState == State.Help || gameState == State.End) {
            menu.render(g);
        }

        g.dispose();
        bs.show();
    }

    public 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 void setUpGame(){
        gameState = State.Game;
        BufferImageLoader loader = new BufferImageLoader();
        LoadImageLevel(loader.loadImage("/src/res/level.png"));
    }

    public void restart(){
        
        handler.clearObjects();

        cam.setX(0);
        cam.setY(0);
        setUpGame();
        gameState = State.Game;
        score=0;

    }

    public static void main(String[] args) {
        new Window(800, 600, "prototype",new Game());
    }
}
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);
        }
    }
    
}
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 abstract Rectangle getBoundsBot();
    public abstract Rectangle getBoundsTop();
    
    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;
    }

}

public class Block extends GameObject{
    
        public Block(float x, float y, ObjectId id){
            super(x, y, id);
        }

        public  void tick(ArrayList <GameObject> object){

        }
        public  void render(Graphics g){
            g.setColor(Color.white);
            g.drawRect((int)x,(int) y, 32, 32);
            /*Graphics2D g2d = (Graphics2D) g;
            g.setColor(Color.red);
            g2d.draw(getBoundsBot());
            //g2d.draw(getBoundsBot());
            g2d.draw(getBounds());*/
        }

        public Rectangle getBoundsTop(){//top
            return new Rectangle((int) x, (int) y, 32,10);
        }
        public Rectangle getBounds(){
            return new Rectangle((int) x, (int) (y), 32, 32);
        }

        public Rectangle getBoundsBot(){
            return new Rectangle((int) x, (int) (y+22), 32,10);
        }
}
public class Handler {

    public ArrayList<GameObject> object = new ArrayList<GameObject>(); //contiene tutti gli oggetti di gioco attivi.

    private GameObject tempObject; //riferimento temporaneo a ciascun oggetto della lista mentre si itera su di essa, posso farne anche a meno

    /* 
    il metodo tick viene chiamato ad ogni ciclo di gioco per aggiornare lo stato di ciascun oggetto
    scorre la lista di tutti gli oggetti di gioco
    Per ogni oggetto, chiama il suo metodo tick() (che è definito nella classe concreta che estende GameObject), 
    */
    public void tick(){
        
        for(int i =0; i< object.size(); i++){
            tempObject = object.get(i);
            
            tempObject.tick(object);
        }
    }

    /*
    Scorre la lista degli oggetti, come nel metodo tick.
    Per ogni oggetto, chiama il suo metodo render(Graphics g) per disegnare l'oggetto
    */
    public void render (Graphics g){
        for(int i = 0; i < object.size(); i++){
            tempObject = object.get(i);
            
            if (tempObject!= null) {
                tempObject.render(g);   
            }
        }
    }

    public void addObject(GameObject object){
        this.object.add(object);
    }

    public void removeObject( GameObject object){
        this.object.remove(object);
    }

    public void clearObjects(){
        object.clear();
    }


}

这些是这个问题需要的主要类

java swing javafx collision-detection gravity
1个回答
0
投票

问题似乎在于,即使玩家在空中,

canSwitchGravity
仍然是
true
。发生这种情况是因为,一旦在与表面碰撞期间将其设置为
true
,当玩家不再接触表面时,它就不会重置为
false

要解决此问题,您需要在碰撞检测开始时将

canSwitchGravity
重置为
false
。这可确保当玩家实际与表面碰撞时,
canSwitchGravity
才为
true

以下是修改

Collision
类中的
Player
方法的方法:

private void Collision(ArrayList<GameObject> objects){
    canSwitchGravity = false;

    for(int i = 0; i < handler.object.size(); i++){
        GameObject tempObject = handler.object.get(i);

        if(tempObject.getId() == ObjectId.Block){

            if (getBoundsTop().intersects(tempObject.getBoundsBot())) {
                y = tempObject.getY() + 32;
                velY = 0;
                canSwitchGravity = true;
            }

            if (getBoundsBot().intersects(tempObject.getBoundsTop())) {
                y = tempObject.getY() - height;
                velY = 0;
                canSwitchGravity = true;
            }
            if (getBounds().intersects(tempObject.getBounds())) {
                x = tempObject.getX() - 32;
            }
            if (getBoundsLeft().intersects(tempObject.getBounds())) {
                x = tempObject.getX() + 32;
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.