Jump to content
  • Advertisement

AWT GUI Facade (4): Draw with tiles

Sign in to follow this  
phylyp

707 views

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:

awtfacade04a.png

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:

awtfacade04b-1024x579.png
  • 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):

awtfacade04c.png
  • 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:

adw_two_buildings.png

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:

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

 

Sign in to follow this  


0 Comments


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Advertisement
  • Blog Entries

  • Similar Content

    • By Blink4Blink
      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? 
    • By Aymen.Khelifi
      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.
    • By MasqCrew
      Hey guys,
      I'm putting together a little thing in Python, a city builder of sorts. Nothing fancy, to be sure. The user will click on buttons to purchase items. In-game currency will be collected via taxes. I'd like to include population growth and pretty much anything that the big city builders keep track of. 
      One of the things I'm not sure how to do is simulate population growth. Each house will have a capacity, so it would be easy to say that a population couldn't grow beyond a certain point (to keep things simple), or if the population grew beyond residential capacity, there would be a homeless population to keep track of (maybe later). What factors would affect population? I'm thinking several things but not sure how to include them in formulas. Building a school could encourage more people to move in. Building other service buildings would help as well. This may not be a game design question (rather something for another forum), but how would you factor in multiple things to raise or lower the chances the population grows?
      And money won't be the only metric. Farms will produce food, which might be needed in order to build restaurants. 
      The pic I've attached shows the very basic and early GUI I'm playing with. Since there won't be any other graphics beyond the buttons (and maybe graphs later), there will be lots of buttons and pages to produce a lot of interactions and gameplay methods.
      I'd love any ideas you have to offer.

    • By Tony Vilgotsky
      Hello, dear colleagues!
      Recently I had a long evening of reflections on the topic, what makes a video game an indie game? Of course, indie projects are the whole niche in this days, but it seems sometimes that when some people are talking about “indie games”, they just don’t know what they are talking about. For some reason many people think that being indie means to be a low-qualified person who is obligated to produce tons of clones of classic games which were hits decades ago. And when they come to game making, they even don’t consider an opportunity to create something more original and interesting. They deliberately produce all these clones. Moreover, with deliberately downgraded graphics, sound and mechanics, which makes sense when it comes to retro scene, but… retro scene is a separate scene and all the indie games don’t have to fit its standards. And then they complain: why nobody is buying this? I think that the answer is obvious: modern gamers prefer modern graphics. So why shoot your own leg, filling your game with pixels, which aren’t even “an art”?
      I’m even silent about the gameplay clones. I think that there should be fewer of them, because indie development is just that thing that gives you freedom to be more original and implement bolder decisions. The world is playing Tetris for 200 years already (correct me if I’m wrong) - and nobody wants to play Tetris with crocodiles instead of bricks.
      It’s sometimes even getting funny: recently I’ve joined a new team (as a junior writer), making a 3D action/adventure game Between Realms with Unreal engine. This is an indie team and indie game, but the goal is to produce a major hit. The game incorporates modern 3D graphics, cutscenes and professional voice overs. And when we posted some stuff from it on the Internet, some people just didn’t believe that we are actually an indie team! I think it’s because modern indie projects almost always belong to the pixel scene or notably simplified from the visual side. So, when we show our materials, some people don’t believe that we belong to indie niche.
      Does it mean that one has to produce simple games with poor 2D pixel graphics to be considered an indie developer?
      From my (and my colleagues’) point of view, indie development must be not a compromise between production speed, expense and quality, but a freedom to create a conceptual product which is not limited by obligatory to sell millions of copies. Those who are tied by this obligatory, are forced to produce standardized, so to say, “tentpole” projects. But with modern technologies the developer is able to create nice, commercially promising, but still an independent project. As developers, we want to raise the bar of indie standard and wish all the rest to reach the same with the games which would be not only original in terms of gameplay but also attractive visually.
      What are you thoughts on this matter? Can a project with budget over $100 be called an indie project? What are the main features of typical indie game? What really makes a game an “indie” game?
    • By vvoodenboy
      Hi!
      My name is... nobodycaresbecauseitsnotimportant.
      I'm working on my own card game. I'm just in a stage of connecting some 'dots' of game's mechanics.
      I'm looking for a concept / 2D artist - because its time to give it some shape - I've a concept of a dark fantasy world where I want to place the plot but there is a lot of space for creativity.
      If you are interested please shout here or on discord (vvoodenboy#3207) or vvoodenboy@gmail.com.
      Have a nice day!
      V
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!