Game AI & Unity/Java Steering game

[Game AI][Steering Behavior] 3. controllers

bay07 2024. 3. 20. 10:39

src 폴더 

  controllers
 Controller

자동차의 방향, 속도, 브레이크를 조절할 수 있도록 하고 있다. 각각 변수를 만든 뒤에 숫자값을 하나씩 주고 있다. 
VARIABLE_STEERING = 0;
VARIABLE_THROTTLE = 1;
VARIABLE_BRAKE = 2;
EmptyController EmptyController는 Controller의 상속을 받고 있는데, controlVariables[] 라는 배열을 새로 만들었다. 그리고 controlVariables
[VARIABLE_STEERING] = 0;

controlVariables[VARIABLE_THROTTLE] = 0;
controlVariables[VARIABLE_BRAKE] = 0;
KeyboardController 찐코드가 적혀있다. 
key_accelerate = KeyEvent.VK_UP;
key_brake = KeyEvent.VK_DOWN;
key_left = KeyEvent.VK_LEFT;
key_right = KeyEvent.VK_RIGHT;

↑ ↓  ← → 이렇게 화살표 키보드를 누를 때마다 그걸 이벤트로 해서 변수값에 담았다. 

그리고 keyboardState에 현재 키값을 받는다. (마지막에 누른 키값)
↓ 가 브레이크라고는 하는데, 게임 플레이 했을때 브레이크인지 잘 몰랐다.
다시한번 플레이 해보면,  ↓ 눌렀을 때 안멈추고 뒤로 가는데..!
이 부분은 조금 더 살펴봐야겠다. 


boolean keyboardState[] = new boolean[KeyEvent.KEY_LAST];
KeyboardState 배열은 모든 키 이벤트의 상태를 저장하기 위한 boolean 배열이다. 
가능한 모든 키를 다 담는 것 


for(int i = 0;i<KeyEvent.KEY_LAST;i++) keyboardState[i] = false;
이 부분은 keyboardState를 모두 false로 초기화를 하는 과정이다. 
아무것도 누르지 않았는데 움직이면 안되니까


KeyEventDispatcher는 키 이벤트를 수신하고 처리하는 데 사용된다.
KEY_PRESSED 이벤트가 발생하면 해당하는 키의 상태를 true로 설정하고,
KEY_RELEASED 이벤트가 발생하면 false로 설정한다.


public
 boolean dispatchKeyEvent(KeyEvent ke) {
        return false;
}
dispatchKeyEvent() 매서드는 항상 false를 반환한다. 이것은 KeyEventDispatcher가 키 이벤트를 처리했으며, 다른 처리기가 추가 호출되지 않도록 한다는 것을 의미한다. 


synchronized (KeyboardController.class) { }
synchronized 블록을 사용하는 이유는, 여러 스레드에서 동시에 키 상태를 업데이트 할 때 동기화하기 위한 것이다. 여러 개의 자동차가 있고, 각각의 자동차를 제어하는 스레드가 동시에 작동했을 때 키 입력을 잘 처리하기 위한 것이다. 


   

 

 

- Controller.java

더보기
package controllers;

import engine.Car;
import engine.Game;

/**
 *
 * @author santi
 */
public abstract class Controller {
    /*
        commands is an array with three components:
        - the desired "STEER" (-1 to +1)
        - the desired "THROTTLE" (0 to +1)
        - the deired "BRAKE" (0 to +1)
    */
    public static final int VARIABLE_STEERING = 0;
    public static final int VARIABLE_THROTTLE = 1;
    public static final int VARIABLE_BRAKE = 2;
    
    public abstract void update(Car subject, Game game, double delta_t, double controlVariables[]);
}

- EmptyController.java

더보기
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package controllers;

import engine.Car;
import engine.Game;
import engine.GameObject;

/**
 *
 * @author santi
 */
public class EmptyController extends Controller {

    public void update(Car subject, Game game, double delta_t, double[] controlVariables) {
        controlVariables[VARIABLE_STEERING] = 0;
        controlVariables[VARIABLE_THROTTLE] = 0;
        controlVariables[VARIABLE_BRAKE] = 0;
    }
    
}

- KeyboardController.java

더보기
package controllers;

import engine.Car;
import engine.Game;
import engine.GameObject;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;

/**
 *
 * @author santi
 */
public class KeyboardController extends Controller {
    public static final int key_accelerate = KeyEvent.VK_UP;
    public static final int key_brake = KeyEvent.VK_DOWN;
    public static final int key_left = KeyEvent.VK_LEFT;
    public static final int key_right = KeyEvent.VK_RIGHT;
    
    
    // store which keys are currently pressed:
    boolean keyboardState[] = new boolean[KeyEvent.KEY_LAST];
    
    public KeyboardController() {
        for(int i = 0;i<KeyEvent.KEY_LAST;i++) keyboardState[i] = false;
        
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(
            new KeyEventDispatcher() {
                public boolean dispatchKeyEvent(KeyEvent ke) {
                    synchronized (KeyboardController.class) {
                        switch (ke.getID()) {
                        case KeyEvent.KEY_PRESSED:
                            keyboardState[ke.getKeyCode()] = true;
//                            System.out.println("pressed: " + ke.getKeyCode());
                            break;

                        case KeyEvent.KEY_RELEASED:
                            keyboardState[ke.getKeyCode()] = false;
                            break;
                        }
                        return false;
                    }
                }
            });        
    }
    
    public void update(Car subject, Game game, double delta_t, double controlVariables[]) {
        controlVariables[VARIABLE_STEERING] = 0;
        controlVariables[VARIABLE_THROTTLE] = 0;
        controlVariables[VARIABLE_BRAKE] = 0;
        
        if (keyboardState[key_left] && !keyboardState[key_right]) controlVariables[VARIABLE_STEERING] = -1;
        if (keyboardState[key_right] && !keyboardState[key_left]) controlVariables[VARIABLE_STEERING] = +1;
        if (keyboardState[key_accelerate]) controlVariables[VARIABLE_THROTTLE] = 1;
        if (keyboardState[key_brake]) controlVariables[VARIABLE_BRAKE] = 1;
    }
    
}