Jump to content
  • Advertisement

Search the Community

Showing results for tags 'Java'.

The search index is currently processing. Current results may not be complete.


More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Categories

  • Audio
    • Music and Sound FX
  • Business
    • Business and Law
    • Career Development
    • Production and Management
  • Game Design
    • Game Design and Theory
    • Writing for Games
    • UX for Games
  • Industry
    • Interviews
    • Event Coverage
  • Programming
    • Artificial Intelligence
    • General and Gameplay Programming
    • Graphics and GPU Programming
    • Engines and Middleware
    • Math and Physics
    • Networking and Multiplayer
  • Visual Arts
  • Archive

Categories

  • Audio
  • Visual Arts
  • Programming
  • Writing

Categories

  • Game Dev Loadout
  • Game Dev Unchained

Categories

  • Game Developers Conference
    • GDC 2017
    • GDC 2018
  • Power-Up Digital Games Conference
    • PDGC I: Words of Wisdom
    • PDGC II: The Devs Strike Back
    • PDGC III: Syntax Error

Forums

  • Audio
    • Music and Sound FX
  • Business
    • Games Career Development
    • Production and Management
    • Games Business and Law
  • Game Design
    • Game Design and Theory
    • Writing for Games
  • Programming
    • Artificial Intelligence
    • Engines and Middleware
    • General and Gameplay Programming
    • Graphics and GPU Programming
    • Math and Physics
    • Networking and Multiplayer
  • Visual Arts
    • 2D and 3D Art
    • Art Critique and Feedback
  • Community
    • GameDev Challenges
    • GDNet+ Member Forum
    • GDNet Lounge
    • GDNet Comments, Suggestions, and Ideas
    • Coding Horrors
    • Your Announcements
    • Hobby Project Classifieds
    • Indie Showcase
    • Article Writing
  • Affiliates
    • NeHe Productions
    • AngelCode
  • Topical
    • Virtual and Augmented Reality
    • News
  • Workshops
    • C# Workshop
    • CPP Workshop
    • Freehand Drawing Workshop
    • Hands-On Interactive Game Development
    • SICP Workshop
    • XNA 4.0 Workshop
  • Archive
    • Topical
    • Affiliates
    • Contests
    • Technical
  • GameDev Challenges's Topics
  • For Beginners's Forum
  • Unreal Engine Users's Unreal Engine Group Forum
  • Unity Developers's Forum
  • Unity Developers's Asset Share

Calendars

  • Community Calendar
  • Games Industry Events
  • Game Jams
  • GameDev Challenges's Schedule

Blogs

There are no results to display.

There are no results to display.

Product Groups

  • Advertisements
  • GameDev Gear

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


About Me


Website


Role


Twitter


Github


Twitch


Steam

Found 45 results

  1. After loading a level, I now propose to add interaction with the use of a mouse. This will be an opportunity to see two other patterns: the Observer Pattern to handle mouse events, and the Game Loop Pattern for synchronization between controls, updates, and display. This post is part of the AWT GUI Facade series Mouse Facade To add the management of the mouse to the facade, I propose to introduce a new Mouse interface that contains all the functions related to the mouse: Separating the interface for the mouse from the general interface of the facade has two advantages: lighten the general interface and allow the simultaneous management of several mice. As far as methods are concerned, I chose the simplest API possible: isButtonPressed() method: returns true if a button is pressed; getX() and getY() methods: return the (x, y) coordinates of the cursor in the window This API is also lowlevel, to match what most graphic libraries offer. In addition, it allows having at any time the complete state of the mouse, which is often necessary for video games. For the general GUIFacade interface, a new getMouse() method is added to return an implementation of the Mouse interface. Mouse handling in AWT To implement this interface, AWT library included in the standard Java library is still used. This one offers a high-level API, which meets the needs of office applications. It is based on the Observer Pattern, which allows an element to observe (or listen to) another element, and to be notified when an event occurs. In the case of the mouse, these events are for example the pressure of a button or the movement of the cursor. This API is divided into several interfaces, for example, the interface MouseListener allows to manage the events related to the buttons: The MouseListener interface contains the methods implemented by the observer: for example, when a button is pressed, the mousePressed() method is called and the observer can then act accordingly. The Component class, which is the superclass of many graphic components within AWT, can be observed by anyone who requests it thanks to the addMouseListener() method. For the example of this article, it is the Canvas used to make the level of the game that is observed: each action of the mouse in its display area causes calls to the methods of the MouseListener interface. Facade implementation I propose that the implementation of the Mouse interface of the facade takes the form of an AWTMouse class: The class implements the Mouse, MouseListener, and MouseMotionListener interfaces. The first methods provide information about the mouse (contained in its attributes): public class AWTMouse implements Mouse, MouseListener, MouseMotionListener { private final boolean[] buttons; private int x; private int y; public AWTMouse() { buttons = new boolean[4]; } @Override public boolean isButtonPressed(int button) { if (button >= buttons.length) { return false; } return buttons[button]; } @Override public int getX() { return x; } @Override public int getY() { return y; } ... The following ones respond to mouse events and update mouse information: @Override public void mouseClicked(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { if (e.getButton() <= 3) { buttons[e.getButton()] = true; } } @Override public void mouseReleased(MouseEvent e) { if (e.getButton() <= 3) { buttons[e.getButton()] = false; } } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } @Override public void mouseDragged(MouseEvent e) { x = e.getX(); y = e.getY(); } @Override public void mouseMoved(MouseEvent e) { x = e.getX(); y = e.getY(); } } Finally, the AWTWindow class contains as before the canvas, and this one is used to “listen” the events of the mouse: public void init(String title, int width, int height) { ... mouse = new AWTMouse(); canvas.addMouseListener(mouse); canvas.addMouseMotionListener(mouse); } Game Loop It only remains to exploit this new interface in an example. To do this, I propose to introduce the Game Loop Pattern in its simplest version (without multi-threaded considerations). It is based on a set of methods that can be grouped together in the same class: The init() method is called at startup to initialize the game and its data; The processInput() method is called at each iteration of the game to manage the controls (keyboard, mouse, …). In short, its main role is to transform the user’s “instructions” into more abstract “orders” or “commands” that the game engine knows how to interpret. Considering time, these operations go to the rhythm of the user. The update() method applies changes to game data based on various sources, such as commands produced by user controls or operations that must be applied to each update. Considering time, these operations go to the speed of the game engine. The render() method handles display. This method will most often order or transfer data on the graphics card, the latter dealing with very low-level tasks at the pixel level. Considering time, these operations go to the refresh rate of the screen (default 60Hz). The run() method calls the previous ones and contains the actual game loop. In this example, I don’t implement all the elements required to meet all these principles. I propose here a basic form of this pattern, sufficient to begin to understand all these notions. For the init() method, we build the two layers and initialize the window: public void init(Level level) { this.level = level; backgroundLayer = gui.createLayer(); backgroundLayer.setTileSize(level.getTileWidth(),level.getTileHeight()); backgroundLayer.setTexture(level.getTilesetImage(0)); backgroundLayer.setSpriteCount(level.getWidth()*level.getHeight()); groundLayer = gui.createLayer(); groundLayer.setTileSize(level.getTileWidth(),level.getTileHeight()); groundLayer.setTexture(level.getTilesetImage(1)); groundLayer.setSpriteCount(level.getWidth()*level.getHeight()); gui.createWindow("Exemple de contrôle avec la souris", scale*level.getTileWidth()*level.getWidth(), scale*level.getTileHeight()*level.getHeight()); } For the processInput() method, if the following conditions are met: the left button is pressed; there is a cell of the level under the cursor; the tile of this cell is in the second set of tiles (the one of the second layer), then we put a tile with grass (this will erase all buildings in the map): public void processInput() { Mouse mouse = gui.getMouse(); if (mouse.isButtonPressed(MouseEvent.BUTTON1)) { int x = mouse.getX() / (scale*level.getTileWidth()); int y = mouse.getY() / (scale*level.getTileHeight()); if (x >= 0 && x < level.getWidth() && y >= 0 && y < level.getHeight()) { if (level.getTileset(x,y) == 1) { level.setTileset(x,y,0); level.setTile(x,y,new Point(7,0)); } } } } For the update() method, the content of the level data is used to define the sprite textures. It is the same as in the previous post, except that this operation is repeated regularly: public void update() { for(int y=0;y<level.getHeight();y++) { for(int x=0;x<level.getWidth();x++) { int index = x + y * level.getWidth(); backgroundLayer.setSpriteLocation(index, new Rectangle(scale*x*level.getTileWidth(), scale*y*level.getTileHeight(), scale*level.getTileWidth(), scale*level.getTileHeight())); if (level.getTileset(x, y) == 0) { Rectangle tile = new Rectangle(level.getTile(x, y), new Dimension(1,1)); backgroundLayer.setSpriteTexture(index, tile); } else { backgroundLayer.setSpriteTexture(index, null); } } } for(int y=0;y<level.getHeight();y++) { for(int x=0;x<level.getWidth();x++) { int index = x + y * level.getWidth(); groundLayer.setSpriteLocation(index, new Rectangle(scale*x*level.getTileWidth(), scale*(y-1)*level.getTileHeight(), scale*level.getTileWidth(), scale*2*level.getTileHeight())); if (level.getTileset(x, y) == 1) { Rectangle tile = new Rectangle(level.getTile(x, y), new Dimension(1,2)); groundLayer.setSpriteTexture(index, tile); } else { groundLayer.setSpriteTexture(index, null); } } } } The render() method just draws the two layers: public void render() { if (gui.beginPaint()) { gui.drawLayer(backgroundLayer); gui.drawLayer(groundLayer); gui.endPaint(); } } Finally, the run() method contains the game loop that calls the other methods at most 60 times per second: public void run() { int fps = 60; long nanoPerFrame = (long) (1000000000.0 / fps); long lastTime = 0; while(!gui.isClosingRequested()) { long nowTime = System.nanoTime(); if ((nowTime-lastTime) < nanoPerFrame) { continue; } lastTime = nowTime; processInput(); update(); render(); long elapsed = System.nanoTime() - lastTime; long milliSleep = (nanoPerFrame - elapsed) / 1000000; if (milliSleep > 0) { try { Thread.sleep (milliSleep); } catch (InterruptedException ex) { ex.printStackTrace(); } } } gui.dispose(); } This basic implementation of the Game Loop pattern does not respect all its principles. There is no real notion of control, and it will be difficult to run each part at different rates. In addition, in terms of design, there are also questionable choices, like the Level class that serves as both a level loader, storage for the level, and a form of buffer. Through future posts, I will present all that is needed to achieve more effective implementations. The code of this post can be downloaded here: awtfacade06.zip To compile: javac com/learngameprog/awtfacade06/Main.java To run: java com.learngameprog.awtfacade06.Main The post AWT GUI Facade (6): Mouse and Game Loop appeared first on Design Patterns and Video Games. View the full article
  2. I'm working on my first Android game and I have a few questions. I need to scale the graphics for different screen sizes/resolutions. I'm working in 16:9 and plan to use letter boxing to maintain this aspect ratio. Everything is fine for standard screen resolutions. Going from 320:180 to 640:360, one pixel just becomes four. I'm a little confused though as to what happens when you letterbox on a screen with a unusual resolution. Say, just for exsample, my original graphics are 160:90. Then to fit the devise I stretch everything by 1.1 and end up with a final resolution of 176:99. Its still 16:9 but now everything is a mess. If I had a sprite that used to be at x-33 y-33 it's new location would now be at x-36.3 y-36.3. Would I just drop the 0.3 of a pixel, round down and accept that it's no longer in its exact position? Secondly what exactly happens when you stretch images by an amount like 1.1? How dose it decide what pixels to add to the image to make it bigger?
  3. I continue the extension of the graphic facade (see previous article), with here the addition of a very classic form of drawing for video games: tiles. These make it possible to compose an image using small images called tiles. There are several types of tiles, I propose in this article the simplest case with rectangular tiles. This post is part of the AWT GUI Facade series. For the implementation, the approach that I propose to follow is similar to the one used for images: we use a factory (Factory Method Pattern) to instantiate layers that allow drawing with tiles. On the GUIFacade main interface side, I add the following two methods, one to create a layer, and the other to draw it: For layers (Layer interface), I propose to manage the tiles with one texture image by layer, and with tiles of a fixed size. In addition, the rendering of tiles can be memorized by the layer: in doing so, it is sufficient to indicate which tiles should be displayed in which places, and then the layer will display these tiles continuously. These renderings are called in this article sprites, so as not to confuse them with tiles (e.g., a tile is just a small picture, and a sprite is a small picture displayed at a specific location on the screen). At this stage of design, layers able to renders independently may seem unnecessary: we could continuously consult the game data for rendering. Later, when it will be necessary to make multi-threaded synchronization, independent layers are a blessing. In addition, for low-level implementations (such as OpenGL), it allows you to use vertex buffers, which greatly speeds up rendering. These properties can be obtained via an interface like the following one: The getTileWidth() and getTileHeight() methods return the size of the tiles (for example, 16 by 16 pixels); The getTextureWidth() and getTextureHeight() methods return the number of tiles in the texture image, in width and height; The setTileSize() method is used to set the size of tiles; The setTexture() method is used to define and load the texture image; The setSpriteCount() method is used to set the number of sprites managed by the layer; The setSpriteTexture() method is used to define the tile used by a sprite. The tile rectangle defines the used tile: they are coordinates in tiles, and not in pixels. For example, if the tile size is 16×16 pixels, and the tile rectangle is (3,4,1,2), then the tile location in pixels is (3 * 16,4 * 16,1 * 16,2 * 16) = (48,64,16,32). By convention, if the rectangle argument is null, then the sprite is disabled; The setSpriteLocation() method is used to define the location where the sprite is drawn. The rectangle is in pixels, and may be larger or smaller than the tiles used, to achieve a zoom effect. AWT Implementation For the implementation, we still use the AWT library, with the AWTLayer class (the methods of the Layer interface are not repeated): The tileWidth, tileHeight, textureWidth, and textureHeight attributes define the size of the tiles and the texture image; The texture attribute contains the texture image; The texture and location arrays contain all sprite information: tiles to use and render locations; The draw() method draws the entire layer. Most methods are accessors / mutators (getters / setters) whose implementation is very simple. The draw () method is less obvious: public void draw(Graphics graphics) { for (int i = 0; i < locations.length; i++) { if (textures[i] != null) { graphics.drawImage(texture, locations[i].x, locations[i].y, locations[i].x + locations[i].width, locations[i].y + locations[i].height, textures[i].x * tileWidth, textures[i].y * tileHeight, (textures[i].x+textures[i].width) * tileWidth, (textures[i].y+textures[i].height) * tileHeight, null); } } } All sprites are traversed (l.2), if a sprite is well defined (l.3), we draw an image (l.4-13). Lines 5 to 8 define the rendering location, in pixels: it is the coordinates of the upper left corner and the lower right corner of the rectangle. Lines 9 to 12 define a rectangle in the texture image: all coordinates are multiplied by tile size (tileWidth, tileHeight). Use case To illustrate this facade with tile drawing, I propose to consider two layers: one for the background, and the other for the buildings. In both cases, we consider the same tile size of 16 × 16 pixels, and the same area of rendering (the level of the game) of 17 × 17 tiles. In addition, a scale factor is used to zoom tiles. These parameters are placed in variables: int scale = 2; int tileWidth = 16; int tileHeight = 16; int levelWidth = 17; int levelHeight = 17; For the background layer, each sprite uses only one tile, and we always use the same one: Layer backgroundLayer = gui.createLayer(); backgroundLayer.setTileSize(tileWidth,tileHeight); backgroundLayer.setTexture("advancewars-tileset1.png"); backgroundLayer.setSpriteCount(levelWidth*levelHeight); for(int y=0;y<levelHeight;y++) { for(int x=0;x<levelWidth;x++) { int index = x + y * levelWidth; backgroundLayer.setSpriteLocation(index, new Rectangle(scale*x*tileWidth, scale*y*tileHeight, scale*tileWidth, scale*tileHeight)); backgroundLayer.setSpriteTexture(index, new Rectangle(new Point(7,0), new Dimension(1,1))); } } Lines 1-4 instantiate and initialize the layer. Then, for each cell of the level (l, 5-6), we associate a sprite (l, 7). To achieve this association, it is necessary to define a unique number for each cell of the level: to do this, the cells are numbered from left to right then from top to bottom. The rendering area of each sprite is defined in lines 8-9, which is a simple scaling: everything is multiplied by the tileWidth, tileHeight, and the global scale. Finally, the tile is selected in lines 10-11, with the 8th column of the first line of the texture Point (7,0) and the size of a tile Dimension (1,1) The following layer is used to display buildings, with the particularity that these have a height of two tiles in height: Layer groundLayer = gui.createLayer(); groundLayer.setTileSize(tileWidth,tileHeight); groundLayer.setTexture("advancewars-tileset2.png"); groundLayer.setSpriteCount(2); groundLayer.setSpriteLocation(0, new Rectangle(scale*8*tileWidth, scale*6*tileHeight, scale*tileWidth, scale*2*tileHeight) ); groundLayer.setSpriteTexture(0, new Rectangle(new Point(0,2), new Dimension(1,2))); groundLayer.setSpriteLocation(1, new Rectangle(scale*8*tileWidth, scale*7*tileHeight, scale*tileWidth, scale*2*tileHeight) ); groundLayer.setSpriteTexture(1, new Rectangle(new Point(0,4), new Dimension(1,2))); Lines 1-4 instantiate the layer and initialize its properties: tile size, texture image, and sprite numbers (2). Lines 6 through 11 define the properties of the first sprite (index 0): its render location is at cell (8,6) of the grid (l. 7), its render size equals a tile width and two heights of tiles (l. 8). Its tiles are at coordinates (0,2) in the texture and use a tile of width one and height two (l. 11). Lines 13 to 18 define the properties of the second sprite: it is drawn on the cell just below, and its tiles start at the coordinates (0,4) in the texture. If all goes well, the top of the second building sprite should cover the bottom of the first: Finally, in the game’s main loop, displaying layers is as easy as displaying an image: if (gui.beginPaint()) { gui.drawLayer(backgroundLayer); gui.drawLayer(groundLayer); gui.endPaint(); } The code of this article can be downloaded here: awtfacade04.zip Some improvements have been made compared to the version of the previous article: it uses a canvas and limits the number of images per second. These improvements are purely related to the problems of video games, and does not change the concepts presented above. To compile: javac com/learngameprog/awtfacade04/Main.java To run: java com.learngameprog.awtfacade04.Main Next post in this series View the full article
  4. In this article, I propose to use the Visitor Pattern to easily load a level. The GUI facade in the previous post is used to display the level. This pattern allows (among other things) to easily browse a data structure to extract information. In our case, it is an XML file created by “Tiled Map Editor” which is analyzed to load a level in memory. This post is part of the AWT GUI Facade series I start by creating a level in XML with Tiled: You have to choose in the left panel Tile layer format as “XML”. This produces an XML file that looks like this: <map version="1.0" orientation="orthogonal" renderorder="left-up" width="16" height="16" tilewidth="16" tileheight="16" nextobjectid="1"> <tileset firstgid="1" name="advancewars-tileset1" tilewidth="16" tileheight="16" tilecount="256"> <image source="advancewars-tileset1.png" width="256" height="256"/> </tileset> <tileset firstgid="257" name="advancewars-tileset2" tilewidth="16" tileheight="16" tilecount="256"> <image source="advancewars-tileset2.png" width="256" height="256"/> </tileset> <layer name="Ground" width="16" height="16"> <data> <tile gid="41"/> <tile gid="41"/> <tile gid="41"/> <tile gid="41"/> <tile gid="41"/> <tile gid="41"/> <tile gid="41"/> <tile gid="41"/> ... <tile gid="41"/> </data> </layer> <layer name="Objects" width="16" height="16"> <data> <tile gid="0"/> <tile gid="0"/> <tile gid="0"/> <tile gid="0"/> <tile gid="0"/> ... <tile gid="0"/> <tile gid="0"/> <tile gid="0"/> </data> </layer> </map> We first have a <main> tag with global properties, then two <tileset> tags that define the tile sets used (one for the background, the other for the objects), and finally two <layer> tags that define the tiles for two layers (one for the background, the other for the objects). To decode this file, I propose to use the XML parser included in the standard Java library. It is based on the Visitor pattern, and allows you to easily work on tags without having to worry about character decoding issues. Visitor Pattern The Visitor pattern can be presented as follows: The IElement interface represents the elements of the structure. In this example, there are two possible types of objects: ElementA and ElementB. The interface requires a method like accept() which takes as argument a visitor who implements the IVisitor interface. There can be several ways to visit the structure, and so many other methods similar to accept(). Parameters can also be used to influence the traversal. The IVisitor interface is implemented by the user who wants to traverse the structured data. In general, the interface methods correspond to the different types of elements that compose it: in this example, they are the ElementA and ElementB classes. It is quite possible to imagine other cases that may interest a user, such as being at the beginning or at the end of an element. In all cases, the accept() method calls the methods of the IVisitor interface according to the cases encountered during its course. Within these methods, the user is free to view and modify the data. Load a level To read and store the level information, I define a Level class that contains this information in attributes: public class Level { private ArrayList<String> tilesetImages = new ArrayList(); private int tileWidth; private int tileHeight; private int width; private int height; private int[][][] level; private int tilesetWidth; private int tilesetHeight; private int x; private int y; ... The tilesetImages attribute contains the file names of texture images; The tileWidth and tileHeight attributes contain the width and height of a tile (16 x 16 pixels in our example); The width and height attributes contain the width and height of the level (16 x 16 cells in our example); The level attribute contains for each cell coordinate: the (x, y) tile coordinates of the tile to draw, and the tile set to use. The following attributes are only used to decode the information in the file. To decode the file, I define a LevelLoader class that implements org.xml.sax.helpers.DefaultHandler. The LevelLoader class is the equivalent of the Visitor class in the diagram above, and DefaultHandler is the equivalent of IVisitor. I’m only interested in the startElement() method, equivalent to the visitElementA() and visitElementB() methods in the diagram above. This method is called whenever the parser encounters a new opening tag: public class LevelLoader extends DefaultHandler { public void startElement (String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("tileset")) { if (tilesetImages.isEmpty()) { tileWidth = Integer.parseInt(attributes.getValue("tilewidth")); tileHeight = Integer.parseInt(attributes.getValue("tileheight")); } } else if (qName.equals("image")) { if (tilesetImages.isEmpty()) { tilesetWidth = Integer.parseInt(attributes.getValue("width")) / tileWidth; tilesetHeight = Integer.parseInt(attributes.getValue("height")) / tileHeight; } tilesetImages.add(attributes.getValue("source")); } else if (qName.equals("layer")) { if (level == null) { width = Integer.parseInt(attributes.getValue("width")); height = Integer.parseInt(attributes.getValue("height")); level = new int[height][width][3]; } x = 0; y = 0; } else if (qName.equals("tile")) { int id = Integer.parseInt(attributes.getValue("gid")); if (id != 0) { if (id >= 257) { level[x][y][2] = 1; id -= 256; level[x][y][0] = id % tilesetWidth - 1; level[x][y][1] = id / tilesetWidth - 1; } else { level[x][y][0] = id % tilesetWidth - 1; level[x][y][1] = id / tilesetWidth; } } x ++; if (x >= width) { x = 0; y ++; if (y > height) { throw new SAXException("Erreur dans le fichier"); } } } } } The method is a long discussion based on the tag encountered, whose name is placed in the qName argument. For the “tileset” and “image” cases the information relating to a set of tiles is decoded. For the “layer” case, the level is initialized, and for “tile”, the information relating to a tile is stored. The x and y attributes are used to store the coordinates of the next tile to be decoded. Finally, I define a load() method in the Level class that uses the LevelLoader class to load the level: public boolean load(String fileName) { try { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); XMLReader xmlReader = saxParser.getXMLReader(); xmlReader.setContentHandler(new LevelLoader()); URL fileURL = this.getClass().getClassLoader().getResource(fileName); xmlReader.parse(fileURL.toString()); return true; } catch(Exception ex) { return false; } } The Level class also has accessors/mutators (getters/setters) not listed here. Display the level To display the level, I use the GUI facade from the previous post: Level level = new Level(); if (!level.load("advancewars-map1.tmx")) { JOptionPane.showMessageDialog(null, "Error when loading advancewars-map1.tmx", "Error", JOptionPane.ERROR_MESSAGE); return; } int scale = 2; Layer backgroundLayer = gui.createLayer(); backgroundLayer.setTileSize(level.getTileWidth(),level.getTileHeight()); backgroundLayer.setTexture(level.getTilesetImage(0)); backgroundLayer.setSpriteCount(level.getWidth()*level.getHeight()); for(int y=0;y<level.getHeight();y++) { for(int x=0;x<level.getWidth();x++) { int index = x + y * level.getWidth(); backgroundLayer.setSpriteLocation(index, new Rectangle(scale*x*level.getTileWidth(), scale*y*level.getTileHeight(), scale*level.getTileWidth(), scale*level.getTileHeight())); if (level.getTileset(x, y) == 0) { Rectangle tile = new Rectangle(level.getTile(x, y), new Dimension(1,1)); backgroundLayer.setSpriteTexture(index, tile); } } } Layer groundLayer = gui.createLayer(); groundLayer.setTileSize(level.getTileWidth(),level.getTileHeight()); groundLayer.setTexture(level.getTilesetImage(1)); groundLayer.setSpriteCount(level.getWidth()*level.getHeight()); for(int y=0;y<level.getHeight();y++) { for(int x=0;x<level.getWidth();x++) { int index = x + y * level.getWidth(); groundLayer.setSpriteLocation(index, new Rectangle(scale*x*level.getTileWidth(), scale*(y-1)*level.getTileHeight(), scale*level.getTileWidth(), scale*2*level.getTileHeight())); if (level.getTileset(x, y) == 1) { Rectangle tile = new Rectangle(level.getTile(x, y), new Dimension(1,2)); groundLayer.setSpriteTexture(index, tile); } } } gui.createWindow("Load a level with the Visitor Pattern", scale*level.getTileWidth()*level.getWidth(), scale*level.getTileHeight()*level.getHeight()); The code of this post can be downloaded here: Download Now! To compile: javac com/learngameprog/awtfacade05/Main.java To run: java com.learngameprog.awtfacade05.Main View the full article
  5. I have been fascinated by programming before 8 years from now. The journey took me from someone who loves to be software engineer to be a networks engineer. I work as full time IP networks engineer. Well, I am a great fun of indie games developers. I have been following Dev-Logs for several indie game developers for a while. In the previous years many ideas of games have been floating in my mind and finally I took the decision to start my own small game project. I have been planning for the last 2 weeks for my game. I have decided to write the whole game and engine myself. My estimations are : Because I am doing this as side project the whole idea ( a 2D platformer ) will take me between 6 months to 1 year. The Game Engine will be developed in parallel with the game I am probably going to Use Java LWJGL or any other OpenGl library I should find a way to target my audience ( probably Youtube channel and dev-logs) Perfectioning the game might have a longer duration than the development of it. I will publish it when it meets the 95% of my expectations If There is any piece of advice of how to start the journey, It will be very helpful. If you have any thoughts about my plan please share it with me. If you have any guidance about how to use this platform I would be more than happy to hear from you. I am just a man who lost his way when making his career related decisions and he is doing a lot of things for fun. Thank you.
  6. The facade seen in the previous article has only an interface with its methods. It is also possible to enrich a facade with additional interfaces, connected to each other by various means. To illustrate it, I propose to add image management. This addition also makes it possible to present another design pattern: the Factory Method Pattern. This post is part of the AWT GUI Facade series. In graphic libraries, it is generally not possible to directly access the raw data of an image, it is always necessary to go through an identifier or a class to apply some processing. Knowing this, a relevant approach is to encapsulate what makes it possible to process the image in a dedicated class, for example: Compared to the previous article, the following methods have been added to the GUIFacade interface: The createImage() method creates an Image from the name of a file. In doing so, we are using the Factory Method pattern, which allows us to abstract the creation of objects, and whose creation process depends on inheritance. In this case, the user of the createImage() method does not know which implementation of the Image interface will be used. This choice depends on the class that implements GUIFacade interface, whose details are not necessarily known to the user, since it is a facade. Once again, the idea is to free the user of specific features, and let him focus on the problem he has to deal with, in our case the rendering of a 2D tile game. The drawImage() method is used to draw an image at (x, y) coordinates. Other methods dedicated to the creation and processing of images can be imagined, these are only examples among others. The Image interface is used to represent access to an image managed by the graphics library. Methods can be proposed to work with an image. In our example, the getWidth() and getHeight() methods return the width and height of the image. Other methods can be imagined, such as a draw() method that would draw the image, instead of the one within the GUIFacade interface. For the implementation of the facade, we still use the AWT library. For the Image interface implementation, an AWTImage class is proposed: public class AWTImage implements Image { private BufferedImage image; @Override public int getWidth() { if (image == null) { throw new RuntimeException("The image was not loaded"); } return image.getWidth(); } @Override public int getHeight() { if (image == null) { throw new RuntimeException("The image was not loaded"); } return image.getHeight(); } void loadImage(String fileName) { try { image = ImageIO.read(this.getClass().getClassLoader().getResource(fileName)); } catch (IOException ex) { throw new RuntimeException("Error when reading "+fileName); } } void draw(Graphics graphics,int x,int y) { graphics.drawImage(image, x, y, null); } } The AWTImage class holds an image reference to a java.awt.image.BufferedImage. getWidth() and getHeight() methods return the width and height of the image. The other two methods are not part of the facade, and are invisible to its users. They are used by the AWTGUIFacade class to load the image (loadImage() method) and display it in a java.awt.Graphics (draw() method): public class AWTGUIFacade implements GUIFacade { ... @Override public Image createImage(String fileName) { AWTImage image = new AWTImage(); image.loadImage(fileName); return image; } @Override public void drawImage(Image image, int x, int y) { if (!(image instanceof AWTImage)) throw new IllegalArgumentException("Invalid image type"); AWTImage awtImage = (AWTImage) image; awtImage.draw(graphics,x,y); } } This new version of the facade can be used in the following way to display a window with an image: public static void run(GUIFacade gui) { Image titleImage = gui.createImage("title.png"); gui.createWindow("AWT Graphic User Interface Facade", titleImage.getWidth(),titleImage.getHeight()); while(!gui.isClosingRequested()) { if (gui.beginPaint()) { gui.drawImage(titleImage,0,0); gui.endPaint(); } } gui.dispose(); } The image is created from the file “title.png” (1. 2), a window of the size of the image is also created (l.3), and as long as the game is not finished (l. 5), the drawing is started (1. 6), the picture is displayed (1. 7) and the drawing is ended (1. 8). The code of this post can be downloaded here: awtfacade03.zip To compile: javac com/learngameprog/awtfacade03/Main.java To run: java com.learngameprog.awtfacade03.Main Next post in this series View the full article
  7. In this article, I propose to continue the design of a facade for a 2D tile game (previous post). I add two new features: creation/destruction of the window, and basic drawing. Each feature is managed by a batch of methods in a GUIFacade interface. This post is part of the AWT GUI Facade series. The GUIFacade interface can be represented in the following way: The first four methods handle the window: The createWindow() method builds the window with a given title; The setClosingRequested() method is used to define whether the game should be completed; The isClosingRequested() method lets you know if the game needs to be completed; The dispose() method destroys the window and all associated elements. The last three methods allow you to draw in the window: The beginPaint() method starts the drawing, and returns true if it is possible; The drawLine() method draws a line. This is an example of a drawing method, a whole collection can be imagined to draw rectangles, circles, etc .; The endPaint() method completes the drawing. Most graphic libraries used to follow these steps where you have to start by “preparing” the drawing with a method like beginPaint(), then “free” it with a method like endPaint(). In addition, there is usually a form of blocking between these two calls, which means that you have to draw “as quickly as possible” if you want to offer a good user experience. These methods can be used as follows: the window is created (l.2) and we repeat until the game is finished (l.3). If it is possible to start drawing (l.4), draw a line (l.5) and finish the drawing (l.6). Finally, the window is destroyed (l. 9): public static void run(GUIFacade gui) { gui.createWindow("AWT GUI Facade"); while(!gui.isClosingRequested()) { if (gui.beginPaint()) { gui.drawLine(100, 150, 600, 350); gui.endPaint(); } } gui.dispose(); } Note: In this example, there is no limitation on the number of frames per second. This can saturate a processor core and cause minor issues on some configurations. We’ll see in another post how to get a better frame rate. The use of the facade does not depend on its implementation: it is possible to use different implementations, for example the AWT library included in the standard Java library: public class AWTGUIFacade implements GUIFacade { private AWTWindow window; private boolean closingRequested = false; private BufferStrategy bufferStrategy; private Graphics graphics; @Override public void createWindow(String title) { window = new AWTWindow(this); window.init(title); window.setLocationRelativeTo(null); window.setVisible(true); window.createBufferStrategy(2); } @Override public void setClosingRequested(boolean b) { closingRequested = b; } @Override public boolean isClosingRequested() { return closingRequested; } @Override public void dispose() { window.dispose(); } @Override public boolean beginPaint() { bufferStrategy = window.getBufferStrategy(); if (bufferStrategy == null) return false; graphics = bufferStrategy.getDrawGraphics(); if (graphics == null) return false; graphics.setColor(Color.black); graphics.fillRect(0, 0, window.getWidth(), window.getHeight()); return true; } @Override public void drawLine(int x1, int y1, int x2, int y2) { graphics.setColor(Color.white); graphics.drawLine(x1, y1, x2, y2); } @Override public void endPaint() { graphics.dispose(); bufferStrategy.show(); } } The window attribute is a reference to an AWTWindow class that inherits from java.awt.Frame, shown below. The closingRequested attribute is true if the game must end. The bufferStrategy and graphics attributes are used to handle double buffering rendering. The init() method is the same as in the previous article, except for the creation of a double buffer with window.createBufferStrategy(2); The setClosingRequested() and isClosingRequested() methods manage the closingRequested attribute. The dispose() method controls the destruction of the window. The beginPaint() and endPaint() methods handle the display cycle. In the first one, the current buffer is obtained (1.37), then a java.awt.Graphics is created from it (1.40). In both situations, various reasons may cause issues, in which case false is returned. The end of the beginPaint() method erases all the content: this approach can be interesting or not, depending on the case. The endPaint() method destroys graphics (1. 56) and inverts the two buffers (1. 57). Finally, the drawLine() method uses graphics to draw a line: it’s easy to imagine other use cases for drawing rectangles, circles, and so on. The AWTWindow class is an AWT window initialized by the init() method with a specific configuration. When window closing is requested by the user, the facade is notified that the game must be completed (1. 16): public class AWTWindow extends Frame { private final AWTGUIFacade gui; public AWTWindow(AWTGUIFacade gui) { this.gui = gui; } public void init(String title) { setTitle(title); setSize(640, 480); setResizable(false); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent we) { gui.setClosingRequested(true); } }); } } Note: The rendering method is simple but not optimal: it is better to use canvas to draw inside a window. This implementation may cause some undesirable effects. The code of this post can be downloaded here: awtfacade02.zip To compile: javac com/learngameprog/awtfacade02/Main.java To run: java com.learngameprog.awtfacade02.Main Next post in this series View the full article
  8. In this series, I propose to discover the Facade Pattern. In short, this pattern defines an interface that allows a reduced and simplified use of a set of features. To illustrate, we design a facade of the AWT graphic library for a 2D tile game. This post is part of the AWT GUI Facade series. Let’s start with the simplest facade with a unique createWindow() method that allows the user to create a new window: Creating a window with this facade is very simple: we instantiate an implementation of the facade (l.1), and call the createWindow() method (l.2): GUIFacade gui = new AWTGUIFacade(); gui.createWindow("AWT GUI Facade"); In this example, I propose to implement a window creation with the AWT library: other implementations are possible without changing the GUIFacade interface and its use. An AWTWindow class that implements java.awt.Frame is defined to handle our window: The createWindow() method of the AWTGUIFacade class instantiates an AWTWindow (l .4), initializes it with a title (l.5), places it in the center of the screen (l.6) and makes it visible (l. 7): public class AWTGUIFacade implements GUIFacade { @Override public void createWindow(String title) { AWTWindow window = new AWTWindow(); window.init(title); window.setLocationRelativeTo(null); window.setVisible(true); } } The AWTWindow class has an init() method that initializes the window with a given title (l.3), a size of 640 by 480 pixels (l.4), prohibits resizing (l.5), and ensures that the window is destroyed when closed (L.6-11): public class AWTWindow extends Frame { public void init(String title) { setTitle(title); setSize(640, 480); setResizable(false); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent we) { dispose(); } }); } } The creation of the window is split between the createWindow() method of the AWTGUIFacade class and the init() method of the AWTWindow class. The main motivation here is to separate the more dynamic operations, such as the position of the window, from more static operations, such as the title or the fact that the window is not designed to be resized. There are many other possibilities depending on the possible extensions of the facade. With this facade, a user can easily create a window for a specific use, without having to know all the methods of a graphic library. Moreover, apart from the instantiation of a layout of the facade (i.e., new AWTGUIFacade()), all the following code no longer depends on the graphic library (the gui variable in the first example code is of type GUIFacade). This means that it is possible to switch from one implementation to another, and therefore from one graphic library to another. This property is very interesting when you want to cross-platform, or if the first choice of the graphic library was not good. In any case, we can switch from one library to another without having to rewrite the entire application! This article presents a very simple first approach, and presents the basics of the facade pattern. In the following articles, things will become more complex, and you will see what can be achieved from a pattern whose principle seems so simple! The code of this post can be downloaded here: awtface01.zip To compile: javac com/learngameprog/awtfacade01/Main.java To run: java com.learngameprog.awtfacade01.Main Next post in this series View the full article
  9. Wograld Homepage Wograld is an open-source 2d multi-player online rpg. We are in need of the following team members. 1.) Marketing. This would just be a get the word out position. Play the alpha, make videos, get it talked about on different forums blogs and youtube channels, or whatever else you can think of. Even if it isn't yet ready for everyone to play, there is nothing like getting everyone all hyped up and excited about the existing game and what new features will be implemented next. I would prefer someone who can already compile and run the game from the latest sources, but if you can't do that yet, I would be willing to spend many hours getting you up to speed for the right (or left) person. 2.) Game mechanics Designer. Okay, I said this is a design position, but I would prefer someone with some basic understanding of the C programing language as well in order to help implement actual code changes.. The main issue is with the game mechanics. Some of them could use some serious tweaking. There is a lot that is fun, and some stuff that really isn't fun. We want to move from the current level system to a more skill based system, but without the grind and macroing that characterized games like Ultima Online. 3.) Java Updater - Unfortunately, this position sounds like the least fun. Who actually wants to take old java code, that works on Java 8, and get it to work on Java 11 and beyond. Maybe someone who wants to prove they can do it and then get a high paying Java developer job after showing off a portfolio. Perhaps someone who is so enthralled with the game idea and also happens to know the latest Java stuff.