Java-Gaming.org Hi !
Featured games (90)
games approved by the League of Dukes
Games in Showcase (741)
Games in Android Showcase (225)
games submitted by our members
Games in WIP (823)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  [SOLVED]I sometric game get what tiles to draw to the screen  (Read 4367 times)
0 Members and 1 Guest are viewing this topic.
Offline hapsburgabsinth

Junior Devvie





« Posted 2014-10-29 08:38:47 »

I just finish drawing a 2d cartesian tile array to an isometric screen.

I now wonder how to get what tiles to draw. As my code is now it draw the tiles within the screen, but it takes the cartesian coordinates, and not the isometric tiles within the screen.

My code for selcting what tiles to draw follows here:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
   public void isometricRender(int xScroll, int yScroll, Screen screen) {
      screen.setOffsets(xScroll, yScroll);
      int x0 = xScroll / Tile.WIDTH;
      int x1 = (xScroll + screen.getWidth() + Tile.WIDTH) / Tile.WIDTH - 1;
      int y0 = yScroll / Tile.HEIGHT;
      int y1 = (yScroll + screen.getHeight() + Tile.WIDTH) / Tile.WIDTH + 1;

      for (int y = y0; y < y1; y++) {
         for (int x = x0; x < x1; x++) {
            getTile(x, y).isometricRender(x, y, screen);
         }
      }

      for (int i = 0; i < _entities.size(); i++) {
         _entities.get(i).isometricRender(screen);
      }

      for (int i = 0; i < _players.size(); i++) {
         // _players.get(i).isometricRender(screen);
      }

      for (int i = 0; i < _projectiles.size(); i++) {
         _projectiles.get(i).isometricRender(screen);
      }
      for (int i = 0; i < _particles.size(); i++) {
         _particles.get(i).isometricRender(screen);
      }
   }


I need help to set the offsets so that it draws the tiles within the screen.

The game looks like this:



Really appriciate you help Smiley
Offline moogie

JGO Ninja


Medals: 16
Projects: 6
Exp: 10 years


Java games rock!


« Reply #1 - Posted 2014-10-29 11:59:52 »

This is the stripped down version of my isometric rendering code I have used for a java4k entry that is on the back burner:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
   private static final int VIEW_PORT_HEIGHT = 20; // in cartesian map scale
   private static final int TILE_SIZE_DIV_2 = 16; // in pixels. half of the tile size
   private static final int MAP_SIZE_MINUS_ONE = 99; // maximum size of the map to be rendered minus one. assuming square map.
   private static final int VIEW_PORT_WIDTH = 30; // in cartesian map scale

   {
      float scrollYScreenUnit=0; // should be updated when scrolling the view port. the unit is in cartesian map scale. i.e. 1 unit = 1 tile  
      float scrollXScreenUnit=0; // should be updated when scrolling the view port. the unit is in cartesian map scale.
     
      int alternateScanline = (int) ((scrollYScreenUnit%1) * 2); // determine whether to start on an "alternative" line. i.e. offset x by half the tile width
      int scrollMapX = (int) ((scrollYScreenUnit+0.5F)+0.5F*(scrollXScreenUnit)); // determine the cartesian co ordinate of the top left corner of the current view.
      int scrollMapY = (int) ((scrollYScreenUnit+0.5F)-0.5F*(scrollXScreenUnit)); // determine the cartesian co ordinate of the top left corner of the current view.

      // iterate over the view port
      for (int vy = -1; vy < VIEW_PORT_HEIGHT*2; vy++)
      {
         alternateScanline=(++alternateScanline)%2;
         int xGame=scrollMapX;  // cartesian co-ordniate of current tile to be rendered
         int yGame=scrollMapY;  // cartesian co-ordniate of current tile to be rendered
         for (int vx = -2; vx < VIEW_PORT_WIDTH ; vx += 2)
         {
            int x = (int) ((xGame-yGame-scrollXScreenUnit-1.0F)*TILE_SIZE_DIV_2); // convert to isometric X
            int y = (int) ((0.5F*(xGame+yGame)-scrollYScreenUnit-0.25F)*TILE_SIZE_DIV_2); // convert to isometric Y
           
            // is the tile visible
            if (xGame > 0 && yGame > 0 && xGame < MAP_SIZE_MINUS_ONE && yGame < MAP_SIZE_MINUS_ONE)
            {
               g.drawImage(images[map[xGame][yGame]], x, y, null); // get the tile from the map at the cartesian co-ordniate and render at isometric coordinates.
            }
   
            xGame++;
            yGame--;
         }
         scrollMapY+=alternateScanline; // update the statring point of the next line of tiles based on whether it is an alternative line
         scrollMapX+=1-alternateScanline; // or not. if it is then the line is shifted out of phase by half.
      }
   }


it may or may not help you as it is not the nicest code around. however it does work (well at least for me Tongue ) as proven by the following screen capture:


Java4k RIP 2014
Offline hapsburgabsinth

Junior Devvie





« Reply #2 - Posted 2014-10-31 07:28:02 »

Quote
1  
2  
3  
4  
   private static final int VIEW_PORT_HEIGHT = 20; // in cartesian map scale
   private static final int TILE_SIZE_DIV_2 = 16; // in pixels. half of the tile size
   private static final int MAP_SIZE_MINUS_ONE = 99; // maximum size of the map to be rendered minus one. assuming square map.
   private static final int VIEW_PORT_WIDTH = 30; // in cartesian map scale

VIEW_PORT_HEIGHT is that the total height of Tiles? And is it the isometric-tiles height?
MAP_SIZE_MINUS_ONE is that the number of tiles to be rendered?
And the same for VIEW_PORT_WIDTH Smiley

Quote
1  
2  
      float scrollYScreenUnit=0; // should be updated when scrolling the view port. the unit is in cartesian map scale. i.e. 1 unit = 1 tile  
      float scrollXScreenUnit=0; // should be updated when scrolling the view port. the unit is in cartesian map scale.

Are these 2 variables for the Screen top-left corner?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline moogie

JGO Ninja


Medals: 16
Projects: 6
Exp: 10 years


Java games rock!


« Reply #3 - Posted 2014-10-31 09:59:57 »

VIEW_PORT_HEIGHT is the "size" of the screen as a multiples of tile height. Similarly with VIEW_PORT_WIDTH is multiples of tile width. Note that my code assumes that the width and heigh of the tiles are the same, however the actual opaque pixels comprising the tile occur from 0.25 to 0.75 of the height of the tile:


 
MAP_SIZE_MINUS_ONE  is just the size of the map array minus one... i.e. int[][] map = new int[100][100] would mean MAP_SIZE_MINUS_ONE is 99

scrollYScreenUnit - yes i believe it is the top left corner... but that can come later... leave as 0 for now.

Java4k RIP 2014
Offline hapsburgabsinth

Junior Devvie





« Reply #4 - Posted 2014-10-31 21:03:43 »

Quote
1  
2  
3  
int alternateScanline = (int) ((scrollYScreenUnit%1) * 2); // determine whether to start on an "alternative" line. i.e. offset x by half the tile width
      int scrollMapX = (int) ((scrollYScreenUnit+0.5F)+0.5F*(scrollXScreenUnit)); // determine the cartesian co ordinate of the top left corner of the current view.
      int scrollMapY = (int) ((scrollYScreenUnit+0.5F)-0.5F*(scrollXScreenUnit)); // determine the cartesian co ordinate of the top left corner of the current view.

alternateScanline <- this is for figuring out if its an odd line right?

scrollMapX and scrollMapY <- these are the coordinates of the top left corner tile in the cartesian map?

Thank you for the help, I really appriciate it Smiley
Offline hapsburgabsinth

Junior Devvie





« Reply #5 - Posted 2014-10-31 21:40:42 »

I've implemented you solution into my game, but now it doesn't render any Tiles on the screen. Maybe some offSet isn't right? The player is rendered in the middle of the screen, but the screen doesn't follow the player, when the player moves, also the movement isn't right... Tongue

Quote
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
public void isometricRender(int xScroll, int yScroll, Screen screen) {
      screen.setOffsets(xScroll, yScroll);
      int VIEW_PORT_HEIGHT = 5; // in cartesian map scale
      int VIEW_PORT_WIDTH = 5; // in cartesian map scale

      float scrollYScreenUnit = 0;
      float scrollXScreenUnit = 0;
      int alternateScanline = (int) ((scrollYScreenUnit % 1) * 2);

      int scrollMapX = (int) ((scrollYScreenUnit + 0.5F) + 0.5F * (scrollXScreenUnit));

      int scrollMapY = (int) ((scrollYScreenUnit + 0.5F) - 0.5F * (scrollXScreenUnit));

      for (int y = -1; y < VIEW_PORT_HEIGHT * 2; y++) {
         alternateScanline = (++alternateScanline) % 2;
         int xGame = scrollMapX;
         int yGame = scrollMapY;

         for (int x = -2; x < VIEW_PORT_WIDTH; x++) {
            int isoX = (int) ((xGame - yGame - scrollXScreenUnit - 1.0F)
                  * Tile.WIDTH / 2);
            int isoY = (int) ((0.5F * (xGame + yGame) - scrollYScreenUnit - 0.25F)
                  * Tile.HEIGHT / 2);

            if (xGame > 0 && yGame > 0 && xGame < _width - 1
                  && yGame < _height - 1) {
               getTile(x, y).render(isoX, isoY, screen);
            }
            xGame++;
            yGame--;
         }
         scrollMapY += alternateScanline;
         scrollMapX += 1 - alternateScanline;
      }
   //Code for render other objects...
}
Offline moogie

JGO Ninja


Medals: 16
Projects: 6
Exp: 10 years


Java games rock!


« Reply #6 - Posted 2014-10-31 22:03:44 »

Well, it does not scroll due to the fact that scrollYScreenUnit is not being updated. What unit is the yScroll in? if it is in pixels then:
1  
2  
scrollYScreenUnit = ((float) yScroll) / Tile.HEIGHT*2;
scrollXScreenUnit = ((float) xScroll) / Tile.WIDTH;


I am not sure what effect the call to screen.setOffsets(xScroll, yScroll) has...

I am suspicious of what getTile(x, y).render(isoX, isoY, screen); does... it should be simply drawing the tile at the isoX, isoY cooridnates. These are in screen co-ordinate space... meaning that 0,0 will be the top left corner of the screen.

Java4k RIP 2014
Offline hapsburgabsinth

Junior Devvie





« Reply #7 - Posted 2014-11-01 05:32:55 »

Quote
I am not sure what effect the call to screen.setOffsets(xScroll, yScroll) has...
xScroll and yScroll is the top-left corner of the cartesian map, with the player centered.

Quote
I am suspicious of what getTile(x, y).render(isoX, isoY, screen)
This method gets the Tile at x,y (cartesian) in the map array, and on that Tile it calls the renderTile method on screen, which draws it to the screen in isometric coordinates.
Offline moogie

JGO Ninja


Medals: 16
Projects: 6
Exp: 10 years


Java games rock!


« Reply #8 - Posted 2014-11-01 09:15:51 »

Quote
I am not sure what effect the call to screen.setOffsets(xScroll, yScroll) has...
xScroll and yScroll is the top-left corner of the cartesian map, with the player centered.

Quote
I am suspicious of what getTile(x, y).render(isoX, isoY, screen)
This method gets the Tile at x,y (cartesian) in the map array, and on that Tile it calls the renderTile method on screen, which draws it to the screen in isometric coordinates.

sure, but how do the two methods interact.... i.e. does calling setOfffsets mean that the later render call has these offsets applied to isoX and isoY? if so then you are doubly taking scrolling into account. The isoX and isoY values already have scrolling taken into account and should be used directly when rendering.

Java4k RIP 2014
Offline hapsburgabsinth

Junior Devvie





« Reply #9 - Posted 2014-11-01 10:26:58 »

Quote
sure, but how do the two methods interact.... i.e. does calling setOfffsets mean that the later render call has these offsets applied to isoX and isoY? if so then you are doubly taking scrolling into account. The isoX and isoY values already have scrolling taken into account and should be used directly when rendering.

Levels isometricRender method:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
public void isometricRender(int xScroll, int yScroll, Screen screen) {
      screen.setOffsets(xScroll, yScroll);
      int VIEW_PORT_HEIGHT = 5; // in cartesian map scale
      // minus one. assuming square map.
      int VIEW_PORT_WIDTH = 5; // in cartesian map scale

      float scrollYScreenUnit = 0; // should be updated when scrolling the
      // view port. the unit is in cartesian
      // map scale. i.e. 1 unit = 1 tile
      float scrollXScreenUnit = 0; // should be updated when scrolling the
      // view port. the unit is in cartesian
      // map scale.

      // determine whether to start on an "alternative" line. i.e. offset x by
      // half the tile width
      int alternateScanline = (int) ((scrollYScreenUnit % 1) * 2);
      // determine the cartesian co ordinate of the top left corner of the
      // current view.

      int scrollMapX = (int) ((scrollYScreenUnit + 0.5F) + 0.5F * (scrollXScreenUnit));
      // determine the cartesian co ordinate of the top left corner of the
      // current view.

      int scrollMapY = (int) ((scrollYScreenUnit + 0.5F) - 0.5F * (scrollXScreenUnit));

      for (int y = -1; y < VIEW_PORT_HEIGHT * 2; y++) {
         alternateScanline = (++alternateScanline) % 2;
         // cartesian co-ordniate of current tile to be rendered
         int xGame = scrollMapX;
         // cartesian co-ordniate of current tile to be rendered
         int yGame = scrollMapY;

         for (int x = -2; x < VIEW_PORT_WIDTH; x++) {
            // convert to isometric X
            int isoX = (int) ((xGame - yGame - scrollXScreenUnit - 1.0F)
                  * Tile.WIDTH / 2);
            // convert to isometric Y
            int isoY = (int) ((0.5F * (xGame + yGame) - scrollYScreenUnit - 0.25F)
                  * Tile.HEIGHT / 2);

            if (xGame > 0 && yGame > 0 && xGame < _width - 1
                  && yGame < _height - 1) {
               getTile(x, y).render(isoX, isoY, screen);
            }
            xGame++;
            yGame--;
         }
         // update the statring point of the next line of tiles based on
         // whether it is an alternative line
         scrollMapY += alternateScanline;
         // or not. if it is then the line is shifted out of phase by half.
         scrollMapX += 1 - alternateScanline;
      }

      for (int i = 0; i < _entities.size(); i++) {
         _entities.get(i).isometricRender(screen);
      }

      for (int i = 0; i < _players.size(); i++) {
         // _players.get(i).isometricRender(screen);
      }

      for (int i = 0; i < _projectiles.size(); i++) {
         _projectiles.get(i).isometricRender(screen);
      }
      for (int i = 0; i < _particles.size(); i++) {
         _particles.get(i).isometricRender(screen);
      }
   }



Render method in Tile:
1  
2  
3  
public void render(int x, int y, Screen screen) {
      screen.renderTile(x * WIDTH, y * HEIGHT, this);
   }


Screens renderTile method:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
public void renderTile(int xp, int yp, Tile tile) {
      xp -= _xOffset;
      yp -= _yOffset;
      int color;
      for (int y = 0; y < tile.getSprite().getHeight(); y++) {
         int ya = y + yp;
         for (int x = 0; x < tile.getSprite().getWidth(); x++) {
            int xa = x + xp;
            if (xa < -tile.getSprite().getWidth() || xa >= _width || ya < 0
                  || ya >= _height) {
               break;
            }
            if (xa < 0) {
               xa = 0;
            }
            color = tile.getSprite().getPixels()[x + y
                  * tile.getSprite().getWidth()];

            if (color != 0xffff00ff) {
               _pixels[xa + ya * _width] = color;
            }
         }
      }
   }


The render method for player:
1  
2  
3  
4  
5  
public void isometricRender(Screen screen) {
      int isoX = (int) Math.round(_x - _y);
      int isoY = (int) Math.round((_x + _y));
      screen.renderNPC(isoX - (SIZE / 2), isoY - (SIZE / 2), _sprite, 0);
   }
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline moogie

JGO Ninja


Medals: 16
Projects: 6
Exp: 10 years


Java games rock!


« Reply #10 - Posted 2014-11-01 11:44:32 »

1  
2  
3  
public void renderTile(int xp, int yp, Tile tile) {
      xp -= _xOffset;
      yp -= _yOffset;


exactly as I had mentioned might be the case... you are doubling applying scrolling... remove this as it is not necessary

Java4k RIP 2014
Offline hapsburgabsinth

Junior Devvie





« Reply #11 - Posted 2014-11-01 12:18:52 »

If I remove the lines which using the offsets in renderTile. It renders the player in the top left corner (0,0) but no tiles. :/
Offline moogie

JGO Ninja


Medals: 16
Projects: 6
Exp: 10 years


Java games rock!


« Reply #12 - Posted 2014-11-01 20:37:06 »

Have you used the debugger at all? i.e. have you determined where the problem is occuring? what values does scrollMapX and scrollMapY produce? is it within the range of your tile map? they both should be 0 if no scrolling has occurred.

How about the isoX and isoY values that are passed into the getTile(x, y).render(isoX, isoY, screen) call... are they within the range of pixels of the screen's width and height?

Java4k RIP 2014
Offline hapsburgabsinth

Junior Devvie





« Reply #13 - Posted 2014-11-02 08:20:33 »

Yes, and it getting me weird outputs Tongue

I think my problem is understading the logic in how to approach this matter. I know that I should figure out the top left corner tile on the scrren, but I am unsure  on how to select the right tiles to draw. Smiley
Offline moogie

JGO Ninja


Medals: 16
Projects: 6
Exp: 10 years


Java games rock!


« Reply #14 - Posted 2014-11-02 12:04:00 »

I can provide complete source of my implementation if desired. Be warned, however that it is probably only going to confuse you more due to the fact that a) it has not been cleaned up in any form, b) it is not completely finished so has a lot of commented out code and c) it was for a java4k entry... thus it is using hacks, dodgy inefficient code so it is not the best to learn from.

Java4k RIP 2014
Offline moogie

JGO Ninja


Medals: 16
Projects: 6
Exp: 10 years


Java games rock!


« Reply #15 - Posted 2014-11-03 06:24:17 »

Here is a standalone version of the program using the code above that was used when making the animated GIF.

Java4k RIP 2014
Offline hapsburgabsinth

Junior Devvie





« Reply #16 - Posted 2014-11-04 05:24:10 »

Thank you for the help so far. I willt ake a closer look at your code Smiley Thnks.
Offline hapsburgabsinth

Junior Devvie





« Reply #17 - Posted 2014-11-04 07:25:32 »

So now I have almost fixed it. I converted the xScroll and yScroll into isometric co-ordinates, and changed the nested-for-loop from cartesian into isometric, and then converted the x and y (in isometric co-ordinates) into cartesian and called the the getTile(cartX,cartY).render(cartX,cartY,screen);

My problem now is, that the screen doesn't scroll fast enough, when you walk left and right. I think that it is the xScroll, that doens't get the right update. The code follows:

Setting the xScroll and yScroll in Games render method:
1  
2  
3  
4  
5  
int xScroll = (int) Math.round((_player.getX() - _player.getY())
            - (_screen.getWidth() / 2));
int yScroll = (int) Math.round((_player.getX() + _player.getY())
            - (_screen.getHeight() / 2));
_level.isometricRender(xScroll, yScroll, _screen);


Render method in Level:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
public void isometricRender(int xScroll, int yScroll, Screen screen) {
      screen.setOffsets(xScroll, yScroll);
      int x0 = xScroll / Tile.WIDTH - 4;
      int x1 = x0 + 11;
      int y0 = yScroll / Tile.HEIGHT;
      int y1 = y0 + 7;

      int cartX = 0;
      int cartY = 0;

      for (int y = y0; y < y1; y++) {
         for (int x = x0; x < x1; x++) {
            cartX = (2 * y + x) / 2;
            cartY = (2 * y - x) / 2;
            getTile(cartX, cartY).isometricRender(cartX, cartY, screen);
         }
      }
}


A little help on understanding how to update the xScroll would be nice.

Thanks in advance Smiley
Offline moogie

JGO Ninja


Medals: 16
Projects: 6
Exp: 10 years


Java games rock!


« Reply #18 - Posted 2014-11-04 08:00:10 »

I am not I can help you... it looks like you have changed the algorithm significantly...

However from looking at your code I am not sure how you are correctly rendering your tiles... it looks like you are just rendering tiles in a grid.... there is no concept of alternating rows of tiles that are out of phase such that they completely cover the screen with no gaps.

But ignoring that issue, you need to be scrolling in isometric space not cartesian space.

Java4k RIP 2014
Pages: [1]
  ignore  |  Print  
 
 

 
Ecumene (107 views)
2017-09-30 02:57:34

theagentd (134 views)
2017-09-26 18:23:31

cybrmynd (244 views)
2017-08-02 12:28:51

cybrmynd (237 views)
2017-08-02 12:19:43

cybrmynd (237 views)
2017-08-02 12:18:09

Sralse (251 views)
2017-07-25 17:13:48

Archive (863 views)
2017-04-27 17:45:51

buddyBro (1006 views)
2017-04-05 03:38:00

CopyableCougar4 (1565 views)
2017-03-24 15:39:42

theagentd (1372 views)
2017-03-24 15:32:08
List of Learning Resources
by elect
2017-03-13 14:05:44

List of Learning Resources
by elect
2017-03-13 14:04:45

SF/X Libraries
by philfrei
2017-03-02 08:45:19

SF/X Libraries
by philfrei
2017-03-02 08:44:05

SF/X Libraries
by SkyAphid
2017-03-02 06:38:56

SF/X Libraries
by SkyAphid
2017-03-02 06:38:32

SF/X Libraries
by SkyAphid
2017-03-02 06:38:05

SF/X Libraries
by SkyAphid
2017-03-02 06:37:51
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!