Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Don't forget to read Tuesday's email newsletter for your chance to win a free copy of Construct 2!


boogyman19946

Member Since 15 May 2010
Offline Last Active Yesterday, 12:44 AM

Topics I've Started

Costs of (Re)Designing a Programming Language

20 April 2014 - 08:56 AM

Hey guys, I have a question that I can't seem to find a resolution to, and I'm not sure where to ask for help.

 

I'm trying to find out what would be the involved cost of changing a part of a programming language's standard. Say for example, if I were Oracle and wanted to change the interface of a class in the Java Programming Language, how much money would I spend to get that accomplished?

 

I tried searching on Google, but I can't find anything on the topic. I figure it might be some kind of a specialty topic that I'm better off asking about. Would anyone know where I can find such information?

 

Thanks in advance!


Figuring out normal force.

25 January 2014 - 03:57 PM

Hello everyone!

 

I have a question that pertains to figuring out normal force. I seem to have a predicament that involves collision detection.

 

At the start I first sum all the forces acting on the object at hand. All external forces come from input or collisions that were maybe applied last cycle. Then all the internal forces: friction, gravity, and normal force. Gravity I can figure out, but figure friction requires me to know the normal but for that I have to know if I'm standing on a platform or not. My question is, is there some elegant way to solve this? For example, is it plausible to just omit the normal force on the first cycle, check collisions and apply the normal force on the next? Or should I make a deliberate check if player is standing on a platform?


Manual Component Resizing

20 January 2014 - 09:48 PM

In Java, does anyone know of some method by which I can let a layout manager resize components, but at the same time keep them in an aspect ratio? Currently the only way I found is to manually resize them, and I can't find a way to do this simply. My general way of constructing UIs is to set the properties of all the components before I add them to a container, and this gives me a lot of grief when it comes to resizing the components because I don't know how much space is available until I add the component to a container and the layout manager sizes it. I thought ComponentListeners would work, but I don't get a componentResized event unless I manually drag the border of the JFrame.


Non-responsive event listener

15 October 2013 - 01:55 PM

I've been having problems getting any kind of input from the window (or anything really) after I start the game. Here's my problem:

I start off the game at the menu and add a key listener and a window listener to the window. So long as I stay in the menu, it works, but as soon as I switch to the panel that draws the game, the listeners all become unresponsive. 

 

I thought the window removes the listeners when I remove the menu panel to replace it with the game panel, however, after I made sure to add the listeners again after the switch, it's still no go. On the other hand, if I switch to the game panel, and then make the game switch back immediately to the menu panel, the listeners all work again. I'm out of ideas at this point. I tried implementing key bindings, but that didn't help, the results were still the same.

 

Here are the four main classes that are involved:

 

Game class - drives core mechanics

package Core.Game;
 
import Core.Menu.MainMenu;
import Core.Menu.PauseMenu;
import Entity.EntityFactory;
import Entity.Systems.AnimationSystem;
import Entity.Systems.ControlSystem;
import Entity.Systems.DrawingSystem;
import Entity.Systems.MotionSystem;
import Graphics.GameCanvas;
import Graphics.GameWindow;
import Input.KeyManager;
import Level.Level;
import Level.LevelLoadingScript;
import Level.World;
import Menu.MenuStack;
import Util.GameTimer;
import java.awt.Color;
import java.awt.event.KeyEvent;
 
public class Game {
   private GameWindow mWindow;
 
   private MenuStack mMenuStack;
 
   private boolean mPaused;
   private boolean mQuit;
 
   private EntityFactory mEntityFactory;
   private Level mLevel;
   private World mWorld;
 
   private GameTimer mFrameTimer;
 
   public Game() {
      mWindow = new GameWindow("Digestion");
      mEntityFactory = new EntityFactory();
      mFrameTimer = new GameTimer();
      mFrameTimer.setTimeInterval( (1/30)*1000 /* 33 millisecond */ );
      mLevel = new Level();
      mWorld = new World();
      mPaused = true;
      setupMenuStack();
   }
 
   private void setupMenuStack() {
      mMenuStack = new MenuStack();
      mWindow.switchTo(mMenuStack);
      MainMenu mainMenu = new MainMenu(this, mMenuStack);
      mainMenu.setBackground(Color.BLACK);
      mMenuStack.pushScreen(mainMenu);
   }
 
   public void startLevel(LevelLoadingScript loadingScript) {
      loadingScript.loadLevel(mLevel);
      loadingScript.createEntities(mEntityFactory, mWorld);
 
      mQuit = false;
 
      GameCanvas canvas = new GameCanvas();
      mWindow.switchTo(canvas);
      execute(canvas);
   }
 
   public void pause() { 
      mPaused = true;
      PauseMenu pauseMenu = new PauseMenu(this, mMenuStack);
      pauseMenu.display();
   }
 
   public void resume() {
      mPaused = false;
   }
 
   public void unpause() { 
      if(mLevel == null)
         return;
 
      mPaused = false;
      mFrameTimer.reset();
   }
 
   private void execute(GameCanvas canvas) {
      unpause();
 
      boolean escProcessed = false;
      while(!mQuit) {
         if(mPaused) {
            if(KeyManager.isKeyPressed(KeyEvent.VK_ESCAPE) && !escProcessed) {
               escProcessed = true;
               resume();
            }
         } else {
            ControlSystem.manipulate(mWorld);
            MotionSystem.move(mWorld);
            AnimationSystem.animate(mWorld);
 
            if(mFrameTimer.hasTimeIntervalPassed()) {
               DrawingSystem.draw(mWorld, canvas);
               canvas.showCanvas();
               mWindow.update();
               mFrameTimer.reset();
            }
 
            if(KeyManager.isKeyPressed(KeyEvent.VK_ESCAPE) && !escProcessed) {
               escProcessed = true;
               pause();
            }
         }
 
         if(!KeyManager.isKeyPressed(KeyEvent.VK_ESCAPE) && escProcessed)
            escProcessed = false;
      }
 
      mPaused = true;
 
      mWindow.switchTo(mMenuStack);
   }
}
 

GameWindow 

package Graphics;
 
import Core.Game.GameWindowListener;
import Input.KeyManager;
import Util.ErrorLog;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
 
public class GameWindow {
   private JFrame mWindow;
 
   private GameWindowListener mWindowListener;
   private KeyManager mKeyDispatcher;
 
   private GraphicsDevice mFullscreenDevice;
   private BufferStrategy mBackBuffer;
 
   private Component mDisplayedItem;
 
   private boolean mFullscreen;
   private int mWidth;
   private int mHeight;
 
   public GameWindow(String title) {
      setupWindow(title);
      loadSettings();
      mWindowListener = new GameWindowListener();
      mKeyDispatcher = new KeyManager();
   }
 
   private void setupWindow(String title) {
      mWindow = new JFrame(title);
      mWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      mWindow.setVisible(true);
      setupBackBuffer();
   }
 
   private void setupBackBuffer() {
      mWindow.createBufferStrategy(2);
      mBackBuffer = mWindow.getBufferStrategy();
   }
 
   private void loadSettings() {
      mFullscreenDevice = null;
      mFullscreen = false;
      setSize(800, 600);
   }
 
   public void switchFullscreen() {
      mFullscreen = !mFullscreen;
 
      if(mFullscreen) {
         switchToFullscreen();
      } else {
         switchToWindow();
      }
   }
 
   private void switchToFullscreen() {
      GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
 
      mFullscreenDevice = env.getDefaultScreenDevice();
      if(mFullscreenDevice.isFullScreenSupported()) {
         mFullscreenDevice.setFullScreenWindow(mWindow);
         mFullscreen = true;
      }
 
      if(!mFullscreen) {
         ErrorLog errorLog = ErrorLog.getInstance();
         errorLog.displayMessageDialog("It seems there are no screens that support fullscreen mode.\nRemaining in Windowed mode");
      }
   }
 
   private void switchToWindow() {
      mFullscreenDevice.setFullScreenWindow(null);
      mFullscreenDevice = null;
 
      mFullscreen = false;
   }
 
   public boolean isFullscreen() {
      return mFullscreen;
   }
 
   public int getWidth() {
      return mWidth;
   }
 
   public int getHeight() {
      return mHeight;
   }
 
   public void setSize(int width, int height) {
      if(mFullscreen) {
         setFullscreenSize(width, height);
      } else {
         setWindowedSize(width, height);
      }
   }
 
   private void setFullscreenSize(int width, int height) {
      mWidth = width;
      mHeight = height;
      mWindow.setSize(width, height);
   }
 
   private void setWindowedSize(int width, int height) {
      Insets insets = mWindow.getInsets();
 
      mWidth = width + insets.left + insets.right;
      mHeight = height + insets.top + insets.bottom;
      mWindow.setSize(width, height);
   }
 
   public void switchTo(Component component) {
      if(mDisplayedItem != null)
         mWindow.remove(mDisplayedItem);
      mWindow.add(component);
      mDisplayedItem = component;
 
      updateListeners();
 
      update();
   }
 
   private void updateListeners() {
      mWindow.addWindowListener(mWindowListener);
 
      KeyboardFocusManager
      .getCurrentKeyboardFocusManager()
      .addKeyEventDispatcher(mKeyDispatcher);
   }
 
   public void update() {
      Graphics g = mBackBuffer.getDrawGraphics();
      mWindow.paintAll(g);
      g.dispose();
      mBackBuffer.show();
   }
}
 

GameCanvas

package Graphics;
 
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import javax.swing.JPanel;
 
public class GameCanvas extends JPanel implements CanvasInterface { 
   private GameViewport mViewport;
   private boolean mViewportEnabled;
 
   private ImageQueue mImageQueue;
 
   public GameCanvas() {
      mViewport = new GameViewport();
      mViewportEnabled = false;
 
      mImageQueue = new ImageQueue();
   }
 
 
   public void setViewport(GameViewport viewport) { 
      mViewport = viewport;
      mViewportEnabled = true;
   }
 
   @Override
   public ColorMode setGraphicsMode(ColorMode newMode) {
      return mImageQueue.setMode(new ColorMode(newMode));
   }
 
   @Override
   public void drawImage(ImageItem imageItem) {
      mImageQueue.addImage(imageItem);
   }
 
   @Override
   public void drawImage(Image image, int x, int y, int z, int width, int height) {
      ImageItem imageItem = new ImageItem();
      imageItem.image = image;
      imageItem.x = x;
      imageItem.y = y;
      imageItem.z = z;
      imageItem.width = width;
      imageItem.height = height;
 
      mImageQueue.addImage(imageItem);
   }
 
   @Override
   public void showCanvas() { 
      repaint();
   }
 
   private void drawItems(Graphics2D g) {
      if(!mViewportEnabled) {
         ImageItem imageItem;
         while(mImageQueue.hasImages()) {
            imageItem = mImageQueue.nextImage(g);
            g.drawImage(imageItem.image, 
                     imageItem.x, 
                     imageItem.y, 
                     imageItem.width, 
                     imageItem.height, 
                     null);
         }
      } else {
         mViewport.update();
 
         Rectangle objectRect = new Rectangle();
         ImageItem imageItem;
         while(mImageQueue.hasImages()) {
            imageItem = mImageQueue.nextImage(g);
            objectRect.x = imageItem.x;
            objectRect.y = imageItem.y;
            objectRect.width = imageItem.width;
            objectRect.height = imageItem.height;
 
            if(!mViewport.contains(objectRect))
               continue;
 
            mViewport.translate(imageItem.x, imageItem.y, imageItem.width, imageItem.height, objectRect);
            g.drawImage(imageItem.image,
                     objectRect.x,
                     objectRect.y,
                     objectRect.width,
                     objectRect.height,
                     null);
         }
      }
   }
 
   @Override
   public void paint(Graphics g) {
      mImageQueue.sort();
 
      drawItems((Graphics2D) g);
   }
}
 

MenuStack - Switches between menu screens (this is the menu panel)

package Menu;
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.util.LinkedList;
import javax.swing.JPanel;
 
public class MenuStack extends JPanel {
   private LinkedList<MenuScreen> mScreenStack;
 
   public MenuStack() {
      mScreenStack = new LinkedList<>();
      setLayout(new BorderLayout());
   }
 
   public void pushScreen(MenuScreen screen) {
      if(!mScreenStack.isEmpty()) 
         remove(mScreenStack.getLast());
      mScreenStack.add(screen);
 
      add(mScreenStack.getLast(), BorderLayout.CENTER);
      revalidate();
      repaint();
   }
 
   public void popScreen() {
      if(mScreenStack.isEmpty())
         return;
 
      remove(mScreenStack.getLast());
      mScreenStack.removeLast();
 
      add(mScreenStack.getLast(), BorderLayout.CENTER);
      repaint();
   }
 
   public MenuScreen currentScreen() {
      return (MenuScreen)getComponent(getComponentCount()-1);
   }
}
 

Sorry to post so much code. Thanks for any help.

 

Edit: fixed all the code formatting. That was weird.


Separating loading/saving functions into a separate class.

06 August 2013 - 05:30 PM

My game has a few objects that load their data from a script file, mainly the level and the game objects. When running the game, I don't mind including the loading functions into the actual object itself because I don't include any way to instantiate them otherwise. In my level editor though, I want to spawn a default level, as well as editing a file where it will be stored. 

 

Here is the two ways I could do this:

Spoiler

 

As per Code Complete 2, it seems to me that I ought to avoid classes that don't have any data to work on. Well that's fine, but adding the LevelLoader functions into Level seems to violate SRP. Also, Clean Code seems to recognize the fact that not everything should be a class, which made me realize the simple fact that LevelLoader is a class only by name really. It should really be just two separate routines. 

 

Is there any preference for any of those approaches?

 


PARTNERS