Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (120)
games submitted by our members
Games in WIP (577)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: 1 [2] 3
  ignore  |  Print  
  Sunland Villagers (was: Learning OpenGL/LWJGL)  (Read 13383 times)
0 Members and 1 Guest are viewing this topic.
Offline Varkas
« Reply #30 - Posted 2012-11-18 21:02:27 »

I've got a basic game actions framework in place now and added two actions to build paths and place buildings. Both functions will be needed in the game, but at the moment it's just proof of concept work.



To make construction a bit easier, there is a helper function to display a little flag on each vertext where an element can be placed:



The strange sand-colored triangle is the map vertex pointer, i.e. the place of which the code thinks you are pointing to with the mouse.

You can get the new demo from here:

https://sourceforge.net/projects/sunlands/files/v0.02/

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline Gjallar

JGO Coder


Medals: 13
Projects: 1


Follower of Nurgle


« Reply #31 - Posted 2012-11-18 21:14:32 »

Works for me!

There was only a white square where the map should be, at the first launch. But after launching it a second time everything worked perfectly. (Assuming that you are only allowed to build a 1 by 1 path at a time)

Nothing in the error log besides:
<?xml version="1.0" encoding="windows-1252" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
</log>
<?xml version="1.0" encoding="windows-1252" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
</log>
<?xml version="1.0" encoding="windows-1252" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
</log>
Offline Varkas
« Reply #32 - Posted 2012-11-18 21:16:43 »

Works for me!

There was only a white square where the map should be, at the first launch. But after launching it a second time everything worked perfectly. (Assuming that you are only allowed to build a 1 by 1 path at a time)

Thanks for the quick test Smiley Path building only works step by step currently, that's right. A bit odd that the display did not initialise correctly for the first try, but at least it worked in the second. Thanks again!

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Varkas
« Reply #33 - Posted 2012-11-20 13:55:07 »

Path building was refined a bit, and a basic UI to chosse from several buildings to build is now in place too. The big building is borrowed from the Widelands project.


if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline Varkas
« Reply #34 - Posted 2012-11-21 11:18:52 »

I've been trying to make the world an island. The water texture was made in a hurry, but I can make a better one later. Also I have kind of proof-of-concept code now to make a decorated border and panel backgrounds.



if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 817
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #35 - Posted 2012-11-21 11:45:52 »

Moved to WIP Pointing

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Varkas
« Reply #36 - Posted 2012-11-21 13:08:59 »

Thanks Smiley

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline matheus23

JGO Kernel


Medals: 109
Projects: 3


You think about my Avatar right now!


« Reply #37 - Posted 2012-11-21 13:41:19 »

Very, Very good progress... reminds me of me, when I was coding a game of a genre I really loved.. Smiley

Also, this looks much more like a game now! Well done!

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline Varkas
« Reply #38 - Posted 2012-11-21 14:33:58 »

Also, this looks much more like a game now! Well done!

Thanks! And yes, at the moment I'm really eager to bring my idea alive. On the other hand, it will be much slower to work on the games logic and better graphics. Particularly the logic will need a lot of planning.

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline RobinB

JGO Ninja


Medals: 44
Projects: 1
Exp: 3 years


Spacegame in progress


« Reply #39 - Posted 2012-11-21 15:22:52 »

Looks very good, i loved the settlers Cheesy
Maybe you should add some more triangles, because those hexagons at the sides of the island dont look to well.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Varkas
« Reply #40 - Posted 2012-11-22 14:29:08 »

Looks very good, i loved the settlers Cheesy

Thanks Smiley

I'll refine the looks of the map and the overall display as the project progresses. There is much to do to make it look better, but I think I know a number of ways to make it look good finally.

Right now I'm quite busy to get some code infrastructure in place to handle workers and workplaces. I hope my approach to have workplaces, which may have one or more workers, and workers which have tasks will suffice and be simple enough to allow swift progress. A tricky thing becuase it involves math is to move the workers over the landscape. Well, the only problem is the calculation of the height, and I hope I can refresh my math related memories to get it right.



The carriers on the paths are just placeholder graphics at the moment. I used them to see if my code for creating workers and moving workers works. It does to some extends, but finding pathes and follollowing them is yet to be done.

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline RobinB

JGO Ninja


Medals: 44
Projects: 1
Exp: 3 years


Spacegame in progress


« Reply #41 - Posted 2012-11-22 16:41:00 »

I was looking at the source, because i was curious how the terrain was lighted (i cant get it to work).
But i dont really get what you are doing:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
    GL11.glBegin(4);
    for (int j = 0; j < this.map.getHeight() - 1; j += 2)
    {
      for (int i = left; i < right; i += 2)
      {
        int normalI = i / 2;
        etc....
      }

      for (int i = left; i < right; i += 2)
      {
        int normalI = i / 2;
        etc....
      }
    }


Are you generating an quad for each 2 pixels, and doing this twice?
Offline Varkas
« Reply #42 - Posted 2012-11-22 22:04:49 »

This code that I produced there must be really confusing for a reader ... sorry.

The map has a zig-zag border left and right. I'll try some ASCII art ... keep in mind each hex is made by 6 triangles, so there is a vertex in the middle of the hex as well (I've left that out in the sketch).

1  
2  
3  
4  
5  
6  
 _
/ \_
\_/ \
/ \_/
\_/ \
  \_/


Every second vertex row is indented by half the edge length. This is the one problem.

The other is, how the triangles are drawn in a row.

1  
\/\/\/


Every second triangle is upside down. And, this order changes for each second row. Even rows start like the sketch above, odd rows start with an upside down triangle.

1  
/\/\/\


So I used two row loops, for the even and the odd rows. I'm sure there is a way to get the vertex positions correctly in one calculation, but I'm not that good at math. And my map structure is basically a 2D array, which is used to store triangles, so it's spaced with a factor of two horizontally (2 triangles in a quad).

Very confusing. Normals are stored in the ordinary spacing, that's why normalI (normal index) is half the triangle index in a row. It's really quite the voodoo code, sorry. I was and still am way too new to the whole 3D and OpenGL topic to produce good and clean code for it yet.

The lighting purely depends on the normals and the light source position. If you want to try it, just draw flat tris/quads and use random normals. This should already give some random wavy bumps even that the surface is actually flat. Sorry again for the magic code there  Undecided

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline Varkas
« Reply #43 - Posted 2012-11-23 11:15:18 »

I've split the game into display-synchroneous actions and asynchroneos actions. Movement and the like is now display-synchroneous, goods creation, good routing and management related taska will be asynchroneous. At the moment there are none of such tasks though, but the infrastructure is in place.

Along with that came some bug fixes to path building and path traversal. I've uploaded a new demo version to Sourceforge to show the current state of development:

http://sourceforge.net/projects/sunlands/files/v0.07/

There are no error checks, so input which the game engine doesn't like will just cause problems. The road workers just run up and down the path endlessly - it's really just some demo code at this point.

Next steps will be to add workers to the buildings and add code to create and manage goods.

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline RobinB

JGO Ninja


Medals: 44
Projects: 1
Exp: 3 years


Spacegame in progress


« Reply #44 - Posted 2012-11-23 13:07:37 »

No its clear what you are doing now.
You dont have to apologise for your code (as long you dont publish it) haha Smiley
But very good work.
Its going to be awsome, im sure about that.
If you want to create an more peacefull version of settlers, have you considered taking some stuff from the Anno series, also loved these games (except the last one) Smiley
Offline RobinB

JGO Ninja


Medals: 44
Projects: 1
Exp: 3 years


Spacegame in progress


« Reply #45 - Posted 2012-11-23 23:16:59 »

Btw check this link about triangle strips: http://dan.lecocq.us/wordpress/2009/12/25/triangle-strip-for-grids-a-construction/.
Maybe it can help you creating the terrain, its very smooth and combined with vbo speedy as fck.
Offline Varkas
« Reply #46 - Posted 2012-11-25 20:58:04 »

Triangle strips will surely speed terrain rendering up a bit, but I feel too lazy to change the code as long as it's not a bottleneck Grin

I've been busy with the workers and the worker management. But I think I have something presentable now. Two workplaces with workers are included, a forester who plants trees, and a woodcutter to cut them down again. Good neighbors for sure Wink And very tireless workers at the moment.



With this in place, it will be easy to add more workplaces and workers. The worker graphics are all just placeholders at the moment, to see if the code works. I'm much better at making houses and trees than I am at making animals and persons ... or anything animated.

The latest demo is here:
https://sourceforge.net/projects/sunlands/files/v0.08/

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline RobinB

JGO Ninja


Medals: 44
Projects: 1
Exp: 3 years


Spacegame in progress


« Reply #47 - Posted 2012-11-26 12:47:09 »

The triangle strip idea was more to fix the messy code Smiley.
It looks great, im really jelous =D
Offline Varkas
« Reply #48 - Posted 2012-11-26 14:08:02 »

Thanks, it's shaping up nicely indeed. There still is a lot of room for improvements though, particlarly more varied landscape textures and better texture transitions. Lately bug tracking and bug fixing starts to take up a good amount of development time, though - up to odd behavior like, if you build a hut right in front of another workers hut, that one can't leave his hut anymore and will eat up more and more CPU time in tries to find a way out  persecutioncomplex

This and a number of other bugs have been remedied in v0.09:
http://sourceforge.net/projects/sunlands/files/v0.09/

If you want to create an more peacefull version of settlers, have you considered taking some stuff from the Anno series, also loved these games (except the last one) Smiley

In the past years I haven't played a lot of games. I often wanted to buy the one or other from the anno series but I nevr did - sometimes they were just too demanding for the computer I had at the time.

Can you help me out with some hints, which features you liked most, and which you'd like to see implemented in Sunland Villagers, too?

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline RobinB

JGO Ninja


Medals: 44
Projects: 1
Exp: 3 years


Spacegame in progress


« Reply #49 - Posted 2012-11-26 14:52:54 »

Thanks, it's shaping up nicely indeed. There still is a lot of room for improvements though, particlarly more varied landscape textures and better texture transitions. Lately bug tracking and bug fixing starts to take up a good amount of development time, though - up to odd behavior like, if you build a hut right in front of another workers hut, that one can't leave his hut anymore and will eat up more and more CPU time in tries to find a way out  persecutioncomplex

This and a number of other bugs have been remedied in v0.09:
http://sourceforge.net/projects/sunlands/files/v0.09/

If you want to create an more peacefull version of settlers, have you considered taking some stuff from the Anno series, also loved these games (except the last one) Smiley

In the past years I haven't played a lot of games. I often wanted to buy the one or other from the anno series but I nevr did - sometimes they were just too demanding for the computer I had at the time.

Can you help me out with some hints, which features you liked most, and which you'd like to see implemented in Sunland Villagers, too?


The main part of the anno series was building up and evolving the economy.
You start with building some of the main resources, like wood and fish.
With wood you can build houses for villagers (they will slowly migrate to your setting) and with fish you can keep the villagers alive.
When your setting has grown a little, these villagers start demanding goods, like wine and wool.
When these demands are satisfied, more people keeps migrating to your settlement until they reach a new civilisation level, with new demands etc..
Soon enough you wont find all of the goods they need on your main island, so you need to claim another island for the other demands.
Also products like bread need an producing system like wheat > flower > bread.


Setting up these chains over multiple islands and turning an "wild" island towards an civilasations is really fun.
The main diffrence is that with an game like settlers you build up producing chains for an army.
With anno it all goes around your residents.
You gotta play it sometimes to see what i mean.
Offline Varkas
« Reply #50 - Posted 2012-11-26 15:13:08 »

Good, that matches quite a lot of my ideas. Thanks for the detailed explanation!

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline Sammyster

Senior Newbie


Medals: 1



« Reply #51 - Posted 2012-11-26 16:13:08 »

This is looking really cool, wasted many hours on the settler series Wink
I'm a bit amazed at how fast you progressed with openGL and this game.
Didn't remember it as that easy when I tried!

Art is starting to come together aswell, made all of it yourself?

Good luck with your project Smiley
Offline Varkas
« Reply #52 - Posted 2012-11-26 22:09:38 »

I started with this tutorial:

http://lwjgl.org/wiki/index.php?title=LWJGL_Basics_3_%28The_Quad%29

It sets up a 2D display for you and you can move quad around. This was already a good start, but the first days were googling and reading tutorials mostly.

The rock/mountain texture and the "headqarter" big building are borrowed from the Widelands project.

Many graphics I had already before I started. The woodcutter hut, the forester hut and the poplar tree I've made during the past week - the photo for the poplar tree I had taken a while ago, expecting that I will need tree images some day soon Grin It's sometimes quite difficult to find single trees to take photos from in a useful angle for games.

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline Varkas
« Reply #53 - Posted 2012-11-28 13:38:14 »

Almost there! But well, you know the last 10% take 90% of the time ...



I think I have the basics in place now. A headqarter which stores goods, a workplace (woodcutter) which produces trunks, another workplace (forester) to plant new trees. Also routing the goods through the path net, and the actual transport with carriers.

I'm quite sure there still is a plethora of bugs and overlooked special cases, but for 2 and half a week, I think this was quite good progress Smiley

http://sourceforge.net/projects/sunlands/files/v0.11/

To test it:

1) Switch to " Buildings", "Large". Select the headquarter (aka storage house).
2) Search for a place on the map which you like and place the headquarter there (click spot).
3) Switch to "Path". Select the path building tool.
4) Build a path to a nearby forest. You can build the path in several segments, each seqment will get a carrier.
5) Switch to "Buildings", "Small", slect the woodcutter.
6) place the woodcutter hut (click spot).
7) Conncet the woodcuuter flag to the path.

It might take a while till the woodcutter made up his mind which tree to cut next. Also he uses to rest between two trees. Also don't worry if the trunks are not carried into the headquarter, but pile up at the flag in front. This is where to current routing code thinks that the destination is. I'll fix this later.

If you made a path building or house placing mistake, try this:

a) Select the "?" Button
b) Click the path flag or building flag which needs to be removed.
c) Confirm "remove" in the popup
d) Building, flag and the adjacent paths will be removed.

Now the project needs map saving and loading ... and more workplaces.

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline Varkas
« Reply #54 - Posted 2012-11-29 10:44:41 »

Also don't worry if the trunks are not carried into the headquarter, but pile up at the flag in front. This is where to current routing code thinks that the destination is. I'll fix this later.

In v0.11a I've added a storekeeper to the headquarter who pulls the goods in. Otherwise it's identical to the v0.11

http://sourceforge.net/projects/sunlands/files/v0.11/

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline RobinB

JGO Ninja


Medals: 44
Projects: 1
Exp: 3 years


Spacegame in progress


« Reply #55 - Posted 2012-11-29 12:31:48 »

Nice work, i only have 3 bugs to rapport:

Terain got messed up when i placed an hut, adding some blue-ish triangle (you really should use more triangles).
Some guy flew over the screen (walked really fast).

Exception (indexoutofbounds):
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  
70  
71  
<?xml version="1.0" encoding="windows-1252" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
  <date>2012-11-29T13:31:18</date>
  <millis>1354192278428</millis>
  <sequence>15</sequence>
  <logger>villagers.Main</logger>
  <level>SEVERE</level>
  <class>villagers.Main</class>
  <method>run</method>
  <thread>1</thread>
  <message>java.lang.IndexOutOfBoundsException: Index: 2, Size: 2</message>
  <exception>
    <message>java.lang.IndexOutOfBoundsException: Index: 2, Size: 2</message>
    <frame>
      <class>java.util.ArrayList</class>
      <method>rangeCheck</method>
    </frame>
    <frame>
      <class>java.util.ArrayList</class>
      <method>get</method>
    </frame>
    <frame>
      <class>villagers.workers.tasks.WalkingTask</class>
      <method>walkAStep</method>
      <line>59</line>
    </frame>
    <frame>
      <class>villagers.workers.Carrier$EnterIdlePosition</class>
      <method>doWork</method>
      <line>166</line>
    </frame>
    <frame>
      <class>villagers.workers.Carrier</class>
      <method>prepareDisplay</method>
      <line>81</line>
    </frame>
    <frame>
      <class>villagers.Map</class>
      <method>prepareDisplay</method>
      <line>330</line>
    </frame>
    <frame>
      <class>villagers.display.GlRenderer</class>
      <method>drawMap</method>
      <line>263</line>
    </frame>
    <frame>
      <class>villagers.display.GlRenderer</class>
      <method>render</method>
      <line>252</line>
    </frame>
    <frame>
      <class>villagers.display.GlRenderer</class>
      <method>run</method>
      <line>755</line>
    </frame>
    <frame>
      <class>villagers.Main</class>
      <method>run</method>
      <line>177</line>
    </frame>
    <frame>
      <class>villagers.Main</class>
      <method>main</method>
      <line>64</line>
    </frame>
  </exception>
</record>
</log>
Offline Varkas
« Reply #56 - Posted 2012-11-29 21:22:43 »

Thanks for testing Smiley

The flying gui might just have been a new carrier, who tried to reach his new workplace (after building a new path). If it was some other event, please let me know and I'll look into it.

The problem that buildings sometimes depress the landscape so much that new water appears (blue areas) will be fixed in the release. In future there will be more checks also and bigger buildings need more open/flat space to be built.

The ArrayIndexOutOfBounds exception came from a carrier, who had a fairly short path. I think I'm going to fix this by making the minimum path length two vertex distances, but I'm not sure at the moment if this is alright.

I hear the wish for a better modelled landscape but I don't want to solve it by adding more, smaller triangles, rather by having better transitions between the textures. Also not quite sure about this one, so I'll wait a bit before doing changes, and try to make up my mind.

Thanks for testing and the reports, this is quite helpful!

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline RobinB

JGO Ninja


Medals: 44
Projects: 1
Exp: 3 years


Spacegame in progress


« Reply #57 - Posted 2012-11-29 21:56:36 »

You are correct about the flying GIU, it occured after i placed an hut.

The terrain bug seemed like an big triangle splitting up, so thats why i gave the comment about more triangles.
I was testing a little with terrain, and with triangles around 32 / 64 pixels, you get very smooth terrain already (see my thread about normals in newb), the triangles in your game seem much bigger.

No problem, i would love to see this game finished Smiley
Offline Varkas
« Reply #58 - Posted 2012-11-30 11:36:40 »

I'll try to get it at least to a playable game Smiley

I've uploaded a new version - it contains a number of bug fixes, but also a fairly big change which might make it more difficult for new people. Buildings can't be placed everywhere anymore, but need a certain amount of fairly flat, open space to be built.

The "Show build helper" function has been expanded a lot to help there, but the updates are a bit slow. So I don't know if it still works well on older computers. The function is now also turned on by default now.

http://sourceforge.net/projects/sunlands/files/v0.12/

I feel a bit uncertain about the changes, and I might have introduced new bugs with them. I also need to learn how to configure the logging properly, at the moment logs are just written to the debug window.

I think the project is at a point now where saving and loading games will be needed. Saving the map is easy enough, but it won't be easy to save all the workers with their tasks and states.

Edit: I forgot to say, the default edge length of the triangles (horizontally) is 100 pixels. You can zoom in and out with the mouse wheel.

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline Varkas
« Reply #59 - Posted 2012-12-02 12:41:02 »

It's been a lot of typing work, but I think I have everything in place now for saving and loading games. Maybe I missed some things, but the new release includes a small demo savegame which seems to save and load properly.

http://sourceforge.net/projects/sunlands/files/v0.14/

To save a game, press ctrls-s. To load a game press ctrl-l. To load the included demo game, just start the game, press ctrl-l, wait a second and it should be there.



There also have been some bugfixes for flag and path handling, and the worker/task classes were overhauled a bit. So some things should work better now, but as usual, I might as well have introduced new bugs while ploughing through the code and adding savegame related routines.

And last but not least, the forester now plants small trees which need some time to grow Smiley

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Pages: 1 [2] 3
  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.

Longarmx (52 views)
2014-10-17 03:59:02

Norakomi (44 views)
2014-10-16 15:22:06

Norakomi (34 views)
2014-10-16 15:20:20

lcass (38 views)
2014-10-15 16:18:58

TehJavaDev (68 views)
2014-10-14 00:39:48

TehJavaDev (68 views)
2014-10-14 00:35:47

TehJavaDev (60 views)
2014-10-14 00:32:37

BurntPizza (73 views)
2014-10-11 23:24:42

BurntPizza (45 views)
2014-10-11 23:10:45

BurntPizza (87 views)
2014-10-11 22:30:10
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!