diff --git a/core/mainThread.java b/core/mainThread.java index 9359e48..af60991 100644 --- a/core/mainThread.java +++ b/core/mainThread.java @@ -61,7 +61,10 @@ public class mainThread extends JFrame implements KeyListener, ActionListener, M public static String timeString; public static boolean fogOfWarDisabled; - + public static Robot myRobot; + + public static boolean capturedMouse; + public static int mouseX, mouseY, centerScreenX, centerScreenY, currentMouseX, currentMouseY; public mainThread(){ setTitle("Battle Tank 3"); @@ -77,7 +80,8 @@ public class mainThread extends JFrame implements KeyListener, ActionListener, M setLocation(dim.width/2-this.getSize().width/2, dim.height/2-this.getSize().height/2); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - + mouseX = 384; + mouseY = 256; //create screen buffer @@ -115,7 +119,14 @@ public class mainThread extends JFrame implements KeyListener, ActionListener, M frameIndex = 0; frameInterval = 25; lastDraw = 0; - + try { + myRobot = new Robot(); + } catch (AWTException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + //create main thread t = new Ticker(0); t.addActionListener(this); @@ -147,6 +158,8 @@ public class mainThread extends JFrame implements KeyListener, ActionListener, M //thread is always lag the main thread by 1 frame. However it is barely noticeable. public void actionPerformed(ActionEvent e){ + + if(frameIndex == 0) { //Add key handler @@ -183,6 +196,16 @@ public class mainThread extends JFrame implements KeyListener, ActionListener, M theGameCursor = new gameCursor(); theGameCursor.init(); + currentMouseX = getLocationOnScreen().x + 384; + currentMouseY = getLocationOnScreen().y + 256; + + centerScreenX = getLocationOnScreen().x + 384; + centerScreenY = getLocationOnScreen().y + 256; + + + if(capturedMouse) + myRobot.mouseMove(centerScreenX, centerScreenY); + //hide mouse cursor // Transparent 16 x 16 pixel cursor image. BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); @@ -195,8 +218,21 @@ public class mainThread extends JFrame implements KeyListener, ActionListener, M this.getContentPane().setCursor(blankCursor); } - frameIndex++; + frameIndex++; + if(capturedMouse) { + if(mouseX < 0) + mouseX = 0; + if(mouseX >= 768) + mouseX = 767; + if(mouseY < 0) + mouseY = 0; + if(mouseY >= 512) + mouseY = 511; + + inputHandler.mouse_x = mouseX; + inputHandler.mouse_y = mouseY; + } inputHandler.processInput(); if(!gamePaused) { @@ -333,16 +369,40 @@ public class mainThread extends JFrame implements KeyListener, ActionListener, M public void mouseDragged(MouseEvent e) { - inputHandler.mouse_x = e.getX(); - inputHandler.mouse_y = e.getY(); + if(capturedMouse) { + currentMouseX = MouseInfo.getPointerInfo().getLocation().x; + currentMouseY = MouseInfo.getPointerInfo().getLocation().y; + + int deltaX = currentMouseX - centerScreenX; + int deltaY = currentMouseY - centerScreenY; + mouseX+=deltaX; + mouseY+=deltaY; + + myRobot.mouseMove(centerScreenX, centerScreenY); + }else { + inputHandler.mouse_x = e.getX(); + inputHandler.mouse_y = e.getY(); + } } public void mouseMoved(MouseEvent e) { - inputHandler.mouse_x = e.getX(); - inputHandler.mouse_y = e.getY(); - + if(capturedMouse) { + currentMouseX = MouseInfo.getPointerInfo().getLocation().x; + currentMouseY = MouseInfo.getPointerInfo().getLocation().y; + + int deltaX = currentMouseX - centerScreenX; + int deltaY = currentMouseY - centerScreenY; + + mouseX+=deltaX; + mouseY+=deltaY; + + myRobot.mouseMove(centerScreenX, centerScreenY); + }else { + inputHandler.mouse_x = e.getX(); + inputHandler.mouse_y = e.getY(); + } } @@ -359,6 +419,9 @@ public class mainThread extends JFrame implements KeyListener, ActionListener, M @Override public void mouseExited(MouseEvent arg0) { inputHandler.mouseIsInsideScreen = false; + + if(capturedMouse) + inputHandler.mouseIsInsideScreen = true; } diff --git a/core/postProcessingThread.java b/core/postProcessingThread.java index e3b7094..84a39a9 100644 --- a/core/postProcessingThread.java +++ b/core/postProcessingThread.java @@ -83,6 +83,7 @@ public class postProcessingThread implements Runnable{ public static String timeString; public static boolean fogOfWarDisabled; + public static boolean capturedMouse; //A pool of vectors which will be used for vector arithmetic public static vector @@ -966,6 +967,9 @@ public class postProcessingThread implements Runnable{ timeString = mainThread.timeString; fogOfWarDisabled = mainThread.fogOfWarDisabled; + capturedMouse = mainThread.capturedMouse; + + currentScreen = mainThread.screen; currentZbuffer = mainThread.zBuffer; diff --git a/gui/button.java b/gui/button.java index 8ae95b7..50d5fbb 100644 --- a/gui/button.java +++ b/gui/button.java @@ -9,6 +9,8 @@ public class button { public char[] theText; public boolean display, cursorIsOnTop; public int actionCooldown; + public int red, green, blue; + public boolean disabled; public button(String name, String text, int xPos, int yPos, int width, int height) { this.name = name; @@ -18,6 +20,7 @@ public class button { this.width = width; this.height = height; theText = text.toCharArray(); + } public boolean checkIfCursorIsOnTop(int mouse_x, int mouse_y) { @@ -27,6 +30,17 @@ public class button { } public void draw(int[] screen) { + if(disabled) { + red = 55; + green = 55; + blue = 55; + }else { + red = 255; + green = 255; + blue = 255; + } + + if(display == false) { cursorIsOnTop = false; return; @@ -59,7 +73,7 @@ public class button { } //draw highlight of cursor is on top of the button - if(cursorIsOnTop) { + if(cursorIsOnTop && !disabled) { R = 239; G = 253; @@ -177,9 +191,9 @@ public class button { //draw text textRenderer tRenderer = postProcessingThread.theTextRenderer; if(text != "x") - tRenderer.drawMenuText(xPos+ (width-tRenderer.getMenuTextWidth(theText))/2,yPos+6,theText, screen, 255,255,255,11); + tRenderer.drawMenuText(xPos+ (width-tRenderer.getMenuTextWidth(theText))/2,yPos+6,theText, screen, red,green,blue,11); else{ - tRenderer.drawMenuText(xPos+ (width-tRenderer.getMenuTextWidth(theText))/2-1,yPos,theText, screen, 255,255,255, 11); + tRenderer.drawMenuText(xPos+ (width-tRenderer.getMenuTextWidth(theText))/2-1,yPos,theText, screen, red,green,blue, 11); } diff --git a/gui/gameCursor.java b/gui/gameCursor.java index cde079a..1a6c716 100644 --- a/gui/gameCursor.java +++ b/gui/gameCursor.java @@ -12,6 +12,7 @@ public class gameCursor { public int[][] arrowIcons; public int[][] smallArrowIcons; + public int[] smallArrowIcons4; public int[] cursorIcon; public int[] screen; @@ -31,6 +32,9 @@ public class gameCursor { cursorIcon = new int[24*24]; loadTexture(folder + "cursor.png", cursorIcon, 24,24); + + smallArrowIcons4 = new int[20*20]; + loadTexture(folder + "smallArrow4.png", smallArrowIcons4, 20,20); } public void updateAndDraw(int[] screen) { @@ -51,6 +55,8 @@ public class gameCursor { boolean cursorIsInSideBar = mainThread.pc.cursorIsInSideBar(); + + if(!mainThread.gamePaused && mainThread.gameStarted) { //draw arrow icons if the player is scrolling the screen with the mouse @@ -152,7 +158,10 @@ public class gameCursor { }else if(hasTroopsSelected && attackKeyPressed) { drawActionIcon(mouseX, mouseY, 1); } + }else if(cursorIsInMiniMap && attackKeyPressed && hasTroopsSelected){ + drawMinimapAttackIcon(mouseX, mouseY); }else { + //draw default icon drawIcon(cursorIcon, mouseX, mouseY); @@ -182,6 +191,38 @@ public class gameCursor { } } + public void drawMinimapAttackIcon(int xPos, int yPos) { + int arrowColor = 240 << 16 | 76 << 8 | 34; + int index = 0; + int color = 0; + int blue = 0; + int red = 0; + + int start = xPos - 10 + (yPos-10)*768; + for(int i = 0; i < 20; i++) { + for(int j = 0; j < 20; j++) { + index = start + j + i*768; + if(index > 0 && index < 393216) { + color = smallArrowIcons4[j+i*20]; + + blue = color&0xff; + red = (color&0xff0000) >> 16; + if(red < 100 && blue > 100) + continue; + + if(!pixelInsideSideArea(index)) + continue; + + if(red > 150) + color = arrowColor; + screen[index] = color; + } + } + } + + + } + public void drawActionIcon(int xPos, int yPos, int type) { xPos-=10; yPos-=10; diff --git a/gui/gameMenu.java b/gui/gameMenu.java index 3bcc818..fb4e472 100644 --- a/gui/gameMenu.java +++ b/gui/gameMenu.java @@ -15,6 +15,7 @@ public class gameMenu { public static final int difficulitySelectionMenu = 1; public static final int helpMenu = 2; public static final int endGameMenu = 3; + public static final int optionMenu = 4; public int[] screen; public int[] screenBlurBuffer; public boolean gameStarted, gamePaused, gameEnded; @@ -23,9 +24,10 @@ public class gameMenu { public int[] titleImage, lightTankImage, rocketTankImage, stealthTankImage, heavyTankImage; - public button newGame, unpauseGame, showHelp, quitGame, abortGame, easyGame, normalGame, hardGame, quitDifficulty, quitHelpMenu, nextPage, previousPage; + public button newGame, unpauseGame, showHelp, showOptions, quitGame, abortGame, easyGame, normalGame, hardGame, quitDifficulty, quitHelpMenu, quitOptionMenu, nextPage, previousPage, + enableMouseCapture, disableMouseCapture, enableFogOfWar, disableFogOfWar; - public char[] easyDescription, normalDescription, hardDescription, helpPage1, helpPage2, helpPage3, helpPage4; + public char[] easyDescription, normalDescription, hardDescription, helpPage1, helpPage2, helpPage3, helpPage4, mouseMode; public int currentHelpPage; @@ -61,6 +63,9 @@ public class gameMenu { showHelp = new button("showHelp", "Help", 324, 160, 120, 28); buttons.add(showHelp); + showOptions = new button("showOptions", "Options", 324, 210, 120, 28); + buttons.add(showOptions); + quitGame = new button("quitGame", "Quit Game", 324, 345, 120, 28); buttons.add(quitGame); @@ -122,17 +127,34 @@ public class gameMenu { + "page: https://github.com/phu004/JavaRTS. If you are intersted in other projects of\n" + "mine, feel free to check out my YouTube channel, user name is \"Pan Hu\".\n\n" + "Have a nice Day!\n\n\n\n\n\n" - + " 4/4" - ).toCharArray(); + + " 4/4").toCharArray(); + + mouseMode = (" Options \n\n\nMouse capture. When enabled the game will prevent \nthe mouse cursor from leaving the current window.\n\n\n" + + "Fog of war. When enabled, enemy units that are not \nin vision will be hidden. Note that your score will NOT \nbe saved when this option is disabled.").toCharArray(); quitHelpMenu = new button("quitHelpMenu", "x", 670, 80, 18,16); buttons.add(quitHelpMenu); + quitOptionMenu = new button("quitOptionMenu", "x", 620, 80, 18,16); + buttons.add(quitOptionMenu); + nextPage = new button("nextPage", "Next Page", 550, 450, 120, 28); buttons.add(nextPage); previousPage = new button("previousPage", "Previous Page", 98, 450, 120, 28); buttons.add(previousPage); + + enableMouseCapture = new button("enableMouseCapture", "Disabled", 545, 145, 80, 25); + buttons.add(enableMouseCapture); + + disableMouseCapture = new button("disableMouseCapture", "Enabled", 545, 145, 80, 25); + buttons.add(disableMouseCapture); + + enableFogOfWar = new button("enableFogOfWar", "Disabled", 545, 215, 80, 25); + buttons.add(enableFogOfWar); + + disableFogOfWar = new button("disableFogOfWar", "Enabled", 545, 215, 80, 25); + buttons.add(disableFogOfWar); } @@ -186,6 +208,7 @@ public class gameMenu { } showHelp.display = true; + showOptions.display = true; }else if(menuStatus == difficulitySelectionMenu) { if(postProcessingThread.escapeKeyPressed) { @@ -197,13 +220,13 @@ public class gameMenu { textRenderer tRenderer = postProcessingThread.theTextRenderer; easyGame.display = true; - tRenderer.drawMenuText(285,118,easyDescription, screen, 255,255,50, 0); + tRenderer.drawMenuText(285,118,easyDescription, screen, 255,255,255, 0); normalGame.display = true; - tRenderer.drawMenuText(285,188,normalDescription, screen, 255,255,50,0); + tRenderer.drawMenuText(285,188,normalDescription, screen, 255,255,255,0); hardGame.display = true; - tRenderer.drawMenuText(285,265,hardDescription, screen, 255,255,50,0); + tRenderer.drawMenuText(285,265,hardDescription, screen, 255,255,255,0); quitDifficulty.display = true; } @@ -245,6 +268,50 @@ public class gameMenu { quitHelpMenu.display = true; } + + + }else if(menuStatus == optionMenu) { + if(postProcessingThread.escapeKeyPressed) { + menuStatus = mainMenu; + + }else{ + if(gameSuspendCount > 0) { + drawBluredBackground(); + } + + drawTitle(); + drawMenuFrame(520, 380); + + textRenderer tRenderer = postProcessingThread.theTextRenderer; + tRenderer.drawMenuText(135,95,mouseMode, screen, 255,255,255,0); + + if(postProcessingThread.capturedMouse == true) { + disableMouseCapture.display = true; + enableMouseCapture.display = false; + }else { + disableMouseCapture.display = false; + enableMouseCapture.display = true; + } + + if(postProcessingThread.fogOfWarDisabled) { + disableFogOfWar.display = false; + enableFogOfWar.display = true; + }else { + disableFogOfWar.display = true; + enableFogOfWar.display = false; + } + + quitOptionMenu.display = true; + + if(postProcessingThread.gameStarted) { + disableFogOfWar.disabled = true; + enableFogOfWar.disabled = true; + }else { + disableFogOfWar.disabled = false; + enableFogOfWar.disabled = false; + } + } + } @@ -260,12 +327,13 @@ public class gameMenu { if(buttons.get(i).actionCooldown == 0 && buttons.get(i).display == true) { buttons.get(i).actionCooldown = 5; - if(buttons.get(i).name == "newGame") { menuStatus = difficulitySelectionMenu; }else if(buttons.get(i).name == "showHelp") { menuStatus = helpMenu; - }else if(buttons.get(i).name == "quitDifficulty" || buttons.get(i).name == "quitHelpMenu") { + }else if(buttons.get(i).name == "showOptions") { + menuStatus = optionMenu; + }else if(buttons.get(i).name == "quitDifficulty" || buttons.get(i).name == "quitHelpMenu" || buttons.get(i).name == "quitOptionMenu") { menuStatus = mainMenu; }else if(buttons.get(i).name == "nextPage") { currentHelpPage++; @@ -475,7 +543,6 @@ public class gameMenu { for(int i = 0; i < 17; i++) { int delta = (int)((d/17)*i); for(int j = 20-delta-1; j < 20-delta; j++) { - int pixel = screen[pos - 17*768 + j + i* 768]; screen[pos - 17*768 + j + i* 768] = ((R1) << 16 | (G1) << 8 | (B1)); } } diff --git a/gui/inputHandler.java b/gui/inputHandler.java index d90e13f..f39e612 100644 --- a/gui/inputHandler.java +++ b/gui/inputHandler.java @@ -45,6 +45,9 @@ public class inputHandler { if(escapePressedCooldown > 0) escapePressedCooldown --; + if(mainThread.capturedMouse) + mouseIsInsideScreen = true; + //read input char int theCounter = inputCounter; @@ -181,12 +184,12 @@ public class inputHandler { mouse_y0 = mouse_y; if(!mouseIsInsideScreen || !mouseMovementArea.contains(mouse_x0, mouse_y0)){ - if(mainThread.pc.cursorIsInMiniMap() || mainThread.pc.cursorIsInSideBar()){ + if(mainThread.pc.cursorIsInMiniMap() || mainThread.pc.cursorIsInSideBar() || mainThread.capturedMouse){ if(mouse_x0 < 10) camera.MOVE_LEFT = true; if(mouse_x0 > 758) camera.MOVE_RIGHT = true; - if(mouse_y0 < 20) + if(mouse_y0 < 10) camera.MOVE_UP = true; if(mouse_y0 > 502) camera.MOVE_DOWN = true; @@ -337,6 +340,18 @@ public class inputHandler { mainThread.gameFrame = 0; mainThread.ec.difficulty = 2; } + + + + + + if(mainThread.buttonAction == "enableFogOfWar") { + mainThread.fogOfWarDisabled = false; + + }else if(mainThread.buttonAction == "disableFogOfWar") { + mainThread.fogOfWarDisabled = true; + + } } //abort current game when the abort button is pressed @@ -345,7 +360,23 @@ public class inputHandler { mainThread.gameFrame = 0; mainThread.gamePaused = false; mainThread.theAssetManager.destoryAsset(); + + camera.MOVE_LEFT = false; + camera.MOVE_RIGHT = false; + camera.MOVE_UP = false; + camera.MOVE_DOWN = false; + camera.TURN_LEFT = false; + camera.TURN_RIGHT = false; } + + //toggle mouse capture mode + if(mainThread.buttonAction == "enableMouseCapture") { + mainThread.capturedMouse = true; + }else if(mainThread.buttonAction == "disableMouseCapture") { + mainThread.capturedMouse = false; + } + + } diff --git a/images/smallArrow4.png b/images/smallArrow4.png new file mode 100644 index 0000000..8b428ef Binary files /dev/null and b/images/smallArrow4.png differ