Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (521)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (589)
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  
  "What you need to do is not confuse logic and rendering."  (Read 5258 times)
0 Members and 1 Guest are viewing this topic.
Offline Dream Of Sleeping
« Posted 2012-04-03 10:04:12 »

The title of this subject is a quote from ra4king, who really seems to know what he is talking about. But unfortunately I've broken this rule REALLY badly in my latest game. I told myself I would just finish this game no matter what and not get bogged down by what convention says I should do, but my code is turning into a great big mess. I would really some advice on how to rewrite  my code without confusing logic and rendering.

I have included two screen shots. I thought this would make it a lot easier to see what I was talking about.




The number tiles are each represented as a Cell object, and they are stored in grid[][]. The user can move those arrows and then move the column and rows. This then moves each cell to its new position in the array. Each cell knows it's row and column. When rendering I do this

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
       // draw cells 
        for (int row = 0; row < grid.length; row++) {
            for (int col = 0; col < grid[row].length; col++) {
               
                Cell cell = grid[row][col];
               
                if (!cell.isFree()) {
   
                    g.drawImage(cell.getImage(), getX(col),
                            getY(row), null);
                    }
            }
        }


The getX(col) method takes the column location of the array and works out it's y coordinate.

Now things get really messy. You see the second screen shot, how the maths symbols are where the user has highlighted. Well I have a class called highlighed line that returns the cells that are highlighted, then in the render method I calculate all the positions of the maths symbols. There is a lot of calculation involved. Don't let this code scare you away, I don't expect you to understand or even read it all, it it's just so you can see what I'm talking about.

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  
 public void renderHighlightedLine(Graphics g) {
        ArrayList<Cell> cells = highlightedLine.getHighlightedCells();
     
        String line = highlightedLine.toString();
       
        int cellCount = 0;
       
        for (int i = 0; i < line.length(); i++) {
            char symbol = line.charAt(i);
           
            if (Character.isDigit(symbol)) {
                int row = cells.get(cellCount).row();
                int col = cells.get(cellCount).col();
                cellCount++;
               
                 g.drawImage(imageLoader.getImage("smallbox"),
                    getX(col), getY(row), null);
            } else if (symbol != '(' && symbol != ')') {
                renderSymbolHighlight(g, symbol, cells.get(cellCount - 1),
                        cells.get(cellCount));
            }
        }
    }
   
    /*
     * Takes the cell locations before and after the symbol to calculate
     * it's position
     */

    public void renderSymbolHighlight(Graphics g, char symbol, Cell cell,
            Cell cell2) {
       
        BufferedImage image = imageLoader.getImage(String.valueOf(symbol));
        int x = 0;
        int y = 0;
        int width = image.getWidth(null) - 5;
        int height = image.getHeight(null) - 5;;
       
        if (cell.row() != cell2.row()) {
           y  = Math.min(getY(cell.row()), getY(cell2.row()));
           y += CELL_SIZE;
           
        } else {
            y = getY(cell.row()) + CELL_SIZE / 2;
        }
       
        if (cell.col() != cell2.col()) {
            x =  Math.min(getX(cell.col()), getX(cell2.col()));
            x += CELL_SIZE;
       
        } else {
            x = getX(cell.col()) + CELL_SIZE / 2;
       }
       
        x -= width / 2;
        y -= height / 2;
       
        g.drawImage(image, x, y, width, height, null);
    }


Now you see the maths problem along the top? I do a similar thing there too.

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  
    public void renderSumProblem(Graphics2D g) {
        int x = 20;
        int y = 65;
        int cellCount = 0;

        int x2 = (stage.getWidth() - problemBorder.getWidth()) / 2; // the x2 is just tempory while i'm working something out
        problemBorder.setX(x2);
        problemBorder.setY(y - 10);
        problemBorder.render(g);
       
        ArrayList<Cell> cells = highlightedLine.getHighlightedCells();
         
        for (int i = 0; i < sumProblem.length(); i++) {
           
            char symbol = sumProblem.charAt(i);
            BufferedImage image;
           
            if (symbol == '_') {
               
                if (cellCount < cells.size()) {
                    Cell cell = cells.get(cellCount);
                    image = cell.getImage();
                   
                } else {
                    // draw question mark
                    image = imageLoader.getImage("_");
                   
                }
               
                if (i != 0 && sumProblem.charAt(0) == '_') {
                    // the previous was a box so add a space
                    x += 1;
                   
                }
                // -1 as cell size is one pixel above the size of the cell images
                g.drawImage(image, x,
                        y + (CELL_SIZE -1  - image.getHeight(null) ) / 2, null);
               
                x += image.getWidth(null);
               
               
                cellCount++;
               
            } else {
                image = imageLoader.getImage(String.valueOf(symbol));
                x += 3;
                g.drawImage(image, x,
                        y + (CELL_SIZE - image.getHeight(null) ) / 2, null);
                x += image.getWidth(null) + 3;
            }
          }
       
        x += 1; // add a small space after = sign
        // if there are numbers after = sign draw them
        for (; cellCount < cells.size(); cellCount++) {
            Cell cell = cells.get(cellCount);
           
            g.drawImage(cell.getImage(), x, y, null);
            x += cell.getImage().getWidth(null) + 1;
        }
    }


I could really do with some help on how to organise this. I don't mind saying, I'm a pretty stupid person, so I won't be offended if you have to really dumb things down for me to understand.


Offline ReBirth
« Reply #1 - Posted 2012-04-03 11:05:06 »

I don't see what's your problem here. As long as your game work, no bug, no time bomb and archieve the desired performance then fine.

What connect between render and logic is variable state. Logic changes it, render draws depend on state's value.

Offline Dream Of Sleeping
« Reply #2 - Posted 2012-04-03 19:13:16 »

Ok thanks. I thought people would point out how horrible that code was. But maybe it's classed as being ok. That's the hardest thing; knowing if I'm writing good or bad code. writing code that works is easy because if it doesn't work I know it, but there is no one to tell me when I'm writing code that is a mess. It's hard to find examples of game source code that's more than two classes.

At the moment all that code was in my GamePlayScene class. I think I need to brake it up into more classes, because at the moment there is like 500 lines of code just rendering, and creating images. It's making it hard to write more code because I am constantly loosing my place.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ra4king

JGO Kernel


Medals: 355
Projects: 3
Exp: 5 years


I'm the King!


« Reply #3 - Posted 2012-04-03 19:35:56 »

In general, your render depends on your logic. However, your logic should not depend on your render. Your render code should not be updating any logic. Your logic code should not be rendering anything.

Offline sproingie

JGO Kernel


Medals: 202



« Reply #4 - Posted 2012-04-03 19:48:40 »

The worst problem here is that Cell might have slightly confused responsibilities here, but otherwise what David Spade here said: don't render as a side effect in your logic, and don't read purely rendering-related state as part of your logic.  

If you really want to create some extra boundaries between your logic and presentation, have Cell implement interfaces like CellContent and CellGraphic, divide up the methods between them, and don't ever cheat by casting.  Then if you get on an elegance kick, then you can factor those out to be more generic (like "Model" and "Drawable") at some future date, and even implement them on separate classes in separate arrays.  I'm not sure any of that's necessary for your app, and you might do just fine with more fine-grained methods that avoid unnecessary statefulness, but it's just one way you can go.


Offline ra4king

JGO Kernel


Medals: 355
Projects: 3
Exp: 5 years


I'm the King!


« Reply #5 - Posted 2012-04-03 22:08:11 »

... but otherwise what David Spade here said...
Grin

Offline ReBirth
« Reply #6 - Posted 2012-04-03 22:33:26 »

If you have bad styled code, it wont disturb anyone except yourself. Harder to read/debug and gain little chance to be reusable.

On my style, I focus to logic. I'll let logic part do everything it likes without touching Graphics/Graphics2D/SpriteBatch. Then I'll be bad on render cause it's only allowed to get values and use +/- for offset sake.

Offline Dream Of Sleeping
« Reply #7 - Posted 2012-04-04 08:04:10 »

Thanks guys! Lots of really valuable information here.

Offline gimbal

JGO Knight


Medals: 25



« Reply #8 - Posted 2012-04-06 13:26:03 »


Whats with that avatar anyway dude? I mean, why David Spade of all people?
Offline ra4king

JGO Kernel


Medals: 355
Projects: 3
Exp: 5 years


I'm the King!


« Reply #9 - Posted 2012-04-06 21:05:19 »

I had no idea who he was at first. I was randomly scrolling through the default images JGO had and I chose him because he looked cool.

Now it's stuck as me Grin

Oh and also because he's dreamy and I want to make lots and lots of babies with him Grin

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline theagentd

« JGO Bitwise Duke »


Medals: 361
Projects: 2
Exp: 8 years



« Reply #10 - Posted 2012-04-07 12:19:42 »

I had no idea who he was at first. I was randomly scrolling through the default images JGO had and I chose him because he looked cool.

Now it's stuck as me Grin

Oh and also because he's dreamy and I want to make lots and lots of babies with him Grin
*pending answer to obvious question of ra4king's sexuality and/or gender*

Myomyomyo.
Offline ReBirth
« Reply #11 - Posted 2012-04-07 14:06:52 »

I had no idea who he was at first. I was randomly scrolling through the default images JGO had and I chose him because he looked cool.

Now it's stuck as me Grin

Oh and also because he's dreamy and I want to make lots and lots of babies with him Grin
*pending answer to obvious question of ra4king's sexuality and/or gender*
I'll give you hint, he's male. Now you have more time to think the other one Tongue

Offline ra4king

JGO Kernel


Medals: 355
Projects: 3
Exp: 5 years


I'm the King!


« Reply #12 - Posted 2012-04-07 22:31:30 »

I had no idea who he was at first. I was randomly scrolling through the default images JGO had and I chose him because he looked cool.

Now it's stuck as me Grin

Oh and also because he's dreamy and I want to make lots and lots of babies with him Grin
*pending answer to obvious question of ra4king's sexuality and/or gender*
Hahahaha I'm a guy and I'm straight. That last line was inspired by sproingie in IRC XD

Offline theagentd

« JGO Bitwise Duke »


Medals: 361
Projects: 2
Exp: 8 years



« Reply #13 - Posted 2012-04-08 07:39:25 »

I had no idea who he was at first. I was randomly scrolling through the default images JGO had and I chose him because he looked cool.

Now it's stuck as me Grin

Oh and also because he's dreamy and I want to make lots and lots of babies with him Grin
*pending answer to obvious question of ra4king's sexuality and/or gender*
Hahahaha I'm a guy and I'm straight. That last line was inspired by sproingie in IRC XD
Great! Glad we cleared that up before any babies got hurt and/or born.

Myomyomyo.
Offline ags1

JGO Wizard


Medals: 72
Projects: 3
Exp: 5 years


Make code not war!


« Reply #14 - Posted 2012-05-30 17:49:42 »

The game looks interesting. If you really want a clean separation between logic and rendering, write the entire logic without any rendering at all. So the logic is only executed by your test code, and it gives back a logical representation of the board in response to any given input. Then use that API to implement your rendering.

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xFryIx (58 views)
2014-11-13 12:34:49

digdugdiggy (37 views)
2014-11-12 21:11:50

digdugdiggy (30 views)
2014-11-12 21:10:15

digdugdiggy (26 views)
2014-11-12 21:09:33

kovacsa (48 views)
2014-11-07 19:57:14

TehJavaDev (51 views)
2014-11-03 22:04:50

BurntPizza (51 views)
2014-11-03 18:54:52

moogie (66 views)
2014-11-03 06:22:04

CopyableCougar4 (65 views)
2014-11-01 23:36:41

DarkCart (150 views)
2014-11-01 14:51:03
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
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!