게임만들기(2) - "JAVADOT" 플랫폼게임

2021. 7. 9. 01:58프로그래밍/개인프로젝트

JavaUI를 이용해서 플랫폼게임을 만드는 과정을 기록합니다.



package JAVADOT_pkg;

import java.util.ArrayList;
import java.util.HashMap;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class JAVADOT_ver2 extends Application {

	private HashMap<KeyCode, Boolean> keys = new HashMap<KeyCode, Boolean>();
	private ArrayList<Node> blocks = new ArrayList<Node>();
	private ArrayList<Node> energys = new ArrayList<Node>();
	private ArrayList<Node> doors = new ArrayList<Node>();
	
	private Node player;
	private int levelWidth;
	private Point2D playerVelocity = new Point2D(0, 0);
	private boolean canJump = true;
    
    private Pane mainContainer = new Pane(); 
	private Pane blockContainer = new Pane();
	
	private Node createObject(int x, int y, int w, int h, Color color) {
        Rectangle object = new Rectangle(w, h);
		object.setTranslateX(x);
		object.setTranslateY(y);
		object.setFill(color);
		blockContainer.getChildren().addAll(object);
		return object;
	} 
    // player, block, energy, door등 사각형 객체를 만드는 클래스
	
	
	private void MainPage() {
		Rectangle bg = new Rectangle(1280, 720, Color.LIGHTGOLDENRODYELLOW);
			// 배경화면만드는 클래스
		levelWidth = ObjectData.LEVEL1[0].length() * 10;
        	// 총 맵 길이
		for (int i = 0; i < ObjectData.LEVEL1.length; i++) {
			// 같은 패키지의 ObjectData파일 참조해서 맵 생성
            String line = ObjectData.LEVEL1[i];
			for (int j = 0; j < line.length(); j++) {
				switch (line.charAt(j)) {
				case '0': // 0이면 빈공간
					break;
				case '1': // 1이면 block
					Node block = createObject(j*10, i*10, 10, 10, Color.LIGHTGREEN);
					blocks.add(block);
					break;
				case '2': // 2면 energy
					Node energy = createObject(j*10, i*10, 5, 5, Color.ORANGE);
					energys.add(energy);
					break;
				case '3': // 3이면 door
					Node door = createObject(j*10, i*10, 10, 10, Color.BLACK);
					doors.add(door);
					break;
				}
			}
		}
		player = createObject(0, 600, 20, 20, Color.DODGERBLUE);
			// player객체 생성
		player.translateXProperty().addListener((obs, old, newValue) -> {
			int offset = newValue.intValue();
			if (offset > 640 && offset < levelWidth - 640) {
				blockContainer.setLayoutX(-(offset - 640));
                //player객체의 X좌표값이 화면절반넘어가면 blockContainer의 위치이동
			}
		});
		
		mainContainer.getChildren().addAll(bg, blockContainer);
        	// mainContainer에 bg와 blockContainer를 자식으로 지정해준다
	}
	
	private boolean isPressed(KeyCode key) {
		return keys.getOrDefault(key, false);
			//keys객체를 만드는 HashMap클래스에 쓰이는 메소드 
			//key가 존재하면 key값을 반환, 존재하지않으면 false 반환
	}
	
	private void sceneUpdate() { // AnimationTimer로 프레임마다 체크
		
		if (isPressed(KeyCode.LEFT) && player.getTranslateX() > 0) { 
			movePlayerX(-6);	
			}
            // 조건이 참이면 movePlayerX의 매개변수로 -6를 입력
		if (isPressed(KeyCode.RIGHT) && player.getTranslateX() + 40 <= levelWidth -  5) { 
			movePlayerX(6);		
			}
            // 조건이 참이면 movePlayerX의 매개변수로 6를 입력
		if (isPressed(KeyCode.SPACE) && player.getTranslateY() > -100) {
			jumpPlayer();
			// 조건이 참이면 jumpPlayer()메소드 실행
		if (playerVelocity.getY() < 10) { 
			playerVelocity = playerVelocity.add(0, 2);	//playerVelocity의 y값이 10보다 작으면 1프레임당 y값 1씩추가
			}
		movePlayerY((int)playerVelocity.getY()); //movePlayerY(int value)에 playerVelocity값 할당 (낙하담당값이라서 연속적으로 실행되야함)
			// 조건이 참이면 playerVelocity에 (0,2) 더해준다
			// movePlayerY에 값 전달
    }
	
	private void movePlayerX(int value) {
		boolean movingRight = value > 0; // LEFT=false, RIGHT=true
		
			for (int i = 0; i < Math.abs(value); i++) {
				for (Node block : blocks) { 
					if (player.getBoundsInParent().intersects(block.getBoundsInParent())) {
						if (movingRight) {	//RIGHT
							if (player.getTranslateX() + 20 == block.getTranslateX()) {
                            // RIGHT 이동시 player의 'x값+20'이 block의 x값과 같다면
								if(player.getTranslateY()+10 < block.getTranslateY()) {
								// player의 y값+10이 block의 y값보다 작다면
                                 	player.setTranslateY(player.getTranslateY()-10);
                                    // player의 y값을 -10해준다
								}
								return;
							}
						} else  {	//LEFT
							if (player.getTranslateX() == block.getTranslateX() + 10) {
                            // LEFT 이동시 player의 x값과 block의 x값+10이 같다면 
								if(player.getTranslateY()+10 < block.getTranslateY()) {
                                // player의 y값+10이 block의 y값보다 작다면 y값을 -10해준다
									player.setTranslateY(player.getTranslateY()-10);
								}
								return;
							}
						}
					}
				}
				player.setTranslateX(player.getTranslateX()+(movingRight ? 1 : -1)); 
                // RIGHT버튼을 누르면 player객체의 x위치를 +1만큼씩, LEFT버튼을 누르면 x위치를 -1만큼씩이동
			}
			for (Node energy : energys) { //일단은 구현만 해놓고 다음에 변경
				if (player.getBoundsInParent().intersects(door.getBoundsInParent())) {
					System.out.println("energy touch");
				}
			}
			for (Node door : doors) { //일단은 구현만 해놓고 다음에 변경
				if (player.getBoundsInParent().intersects(door.getBoundsInParent())) {
					System.out.println("door touch");
				}
			}
		}
	private void movePlayerY(int value) {
		boolean movingDown = value > 0;
				
				for (int i = 0; i < Math.abs(value); i++) {
					for (Node block : blocks) {
						if (player.getBoundsInParent().intersects(block.getBoundsInParent())) {
                        //player와 block비교
							if (movingDown) {
								if (player.getTranslateY() + 20 == block.getTranslateY()) {
                                // player객체 y값 +20(객체높이) = block객체 y값이면
									player.setTranslateY(player.getTranslateY() - 1);
									canJump=true;
                                    // player객체의 y값을 -1해주고 canJump메소드 활성화
									return;
								}
							} else {
								if (player.getTranslateY() == block.getTranslateY() + 9) {
									canJump=false;
                                    // 점프시 윗벽이 막혀있으면 더 안올라가짐
									return;
								}
							}
						}
					}
					player.setTranslateY(player.getTranslateY()+(movingDown ? 1 : -1));
                    //player객체의 위치 = player객체의 이동좌표+ movingDown이 참이라면 +1 거짓이면 -1
				}
				for (Node door : energys) { //일단은 구현만 해놓고 다음에 변경
					if (player.getBoundsInParent().intersects(door.getBoundsInParent())) {
						System.out.println("energy touch");
					}
				}
				for (Node door : doors) { //일단은 구현만 해놓고 다음에 변경
					if (player.getBoundsInParent().intersects(door.getBoundsInParent())) {
						System.out.println("door touch");
					}
				}
			}
	//
	private void jumpPlayer() {
		if (canJump) {
			playerVelocity = playerVelocity.add(0, -35);
			canJump = false;
		}
	}
	
	//
	@Override
	public void start(Stage primaryStage) {
		
		MainPage();
		
		Scene scene = new Scene(mainContainer);
		scene.setOnKeyPressed(e -> keys.put(e.getCode(), true));
		scene.setOnKeyReleased(e -> keys.put(e.getCode(), false));
		primaryStage.setTitle("JAVADOT");
		primaryStage.setScene(scene);
		primaryStage.show();
		
		AnimationTimer timer = new AnimationTimer() {
			@Override
			public void handle(long now) {
				sceneUpdate();
			}
		};
		timer.start();
		
	}

	public static void main(String[] args) {
		launch(args);
	}
}

오늘 한 것 :

ArrayList를 이용해서 각종 객체 구현,

player객체 좌/우 이동구현, 점프구현, 경사이동구현, 낙하구현, 이동시 화면이동구현

player 와 block 충돌구현, 

 

내일 할 것 : 
점프횟수제한 (1이상일때만 점프가능, 점프시 -1, Label객체를 통해 시각화)

player와 energy 충돌구현( 획득시 점프횟수 +1, 충돌시 사라지게하기)