If anyone can help me get shadows working so that blocks can produce shadows, or help me implement a better lighting system it would be much appreciated, It's my first real game so I'm not quite sure how to go about it...

I made something like that a few weeks ago. I'll try to explain what I made:

-First af all, the Tile class should have a variable lightLevel or something like that, set it to 0. That way that tile won't be visible.(You can also make that if the light level is 0 don't draw that tile for better performance );

-On the draw method of the tile I used some black images with different alpha values . So first draw the tile and the alpha images just above. Make a switch or if's and select the image according to the lightLevel.

-Draw a map using an array of Tiles.

-On the torch class I made that:

1 2 3 4 5 6 7 8 9 10 11 12

publicTorch(intx, inty){

//change the light livel of all the adjacent tiles(make the shape that you want)Map.tiles[x][y].lightLevel=0; Map.tiles[x+1][y].lightLevel=1;Map.tiles[x+2][y].lightLevel=1; Map.tiles[x+3][y].lightLevel=2; Map.tiles[x][y+1].lightLevel=1;Map.tiles[x][y+2].lightLevel=1;

//...and many more}

So, when you place a torch on the map it will assign the lightLevel.

I hope it's understable. Man, I suggest you to use more classes, it will simplify your work so much.

Ah, fair enough, it's slightly similar in that you're using alpha-ed black images and I'm using alpha-ed black squares, I was planning on moving the torches stuff in to it's own class, but you're right I should give the tiles their own class, that'll simplify things later. Also, did you have any shadows in yours or did you not bother?

1. As far as I know, it is not common to store game maps as 2 dimensional arrays of bufferedImages. This makes any sort of logic look quite messy and usually people tend towards having 2d arrays of ints if the tiles aren't dynamic (or enumerations, if you like to keep it easy to read) (if they are dynamic, give them their own classes), which represent tiles, and are later converted by the renderer to render a static bufferedImage which represents that tile number. Using ints allows you to say:

if(tileNumber>=0 && tilenumber<=20){ //where only floor tiles have IDs between 0 and 20//do stuff specific to all floor tiles}

That might not work completely, i just quickly typed it up in notepad, and there are some sections you need to fill in for yourself where I have just used pseudocode. You just need to check this before you light a tile, each time you were thinking of lighting a tile, and it will create sharp shadows, which are not completely realistic, but some people like 'em. If you wanted them with blurry edges there are a few different paths you could take, but just experiment! that code there should get the hard bit out of the way, but once you understand what I've written, you could customise it to include translucency, mirrors, coloured lighting, all sorts of stuff!.

One more thing, i'm not sure what you're doing with the lighting at the moment, but there is no need to redo the lighting every frame, only whenever you change something in the area of the torch.

Wow, thats really helpful thanks!, with the everything posted here I should be able to take a good swing at getting this working. But I'm off to bed as I'm tired...I'll make sure to post up progress later this week.

Sorry, I slept on that code and realised that it would not work for line gradients of greater than 1, because it would miss out bits of the line checking. A method I have used in the past is to, if the gradient is greater than 1, do 1/gradient and step by y++ rather than x++.

But this makes a huge mess of code, surely someone can think of a better way?

Determing visibility between a light and a tile is pretty easy, just raycast between them and check if there´s something in between. The problem here is performance. Doubling the radius of a light quadrouples the area the light covers, and therefore the number of raycasts. However, the raycasts also get a LOT more expensive since the extra raycasts needed are twice as long. In the end this scales VERY badly with larger lights, but if you only have a handful of lights with a radius of around 10 tiles or so you should be able to get realtime frame rates pretty easily.

I encountered the exact same problem when I was doing fog of war with "shadows" from walls. I ended up uploading a "wall map" to a texture and then doing the raycasts in a shader on the GPU for each tile. I got antialiased shadows thanks to free texture interpolation of the wall map, very simple code and almost no CPU cost at all since it´s handled by the GPU. Performance of lights with a radius of 10 tiles: around 50 000 lights at 60 FPS on relatively low end computers. Increasing the light size still has a very high cost though...

Raycasting is the fancy name for what I described, all you need is an algorithm to draw a line. You could finish the one I started, make your own, or google the 'Bresenham algorithm' for more information on how to calculate lines efficiently

Take into mind what theagentd said, about the lights scaling badly. But be sure you only update the lights every frame if you absolutely need to. If the lighting isn't going to change, You only need to calculate lighting when the level starts.If you can place your own blocks or lights, you only need to update that affects that area when you place a block/torch.

My code won't work correctly for gradients above 1 because if you have a gradient below one, you need to increment the x value several times to see a change in the integer value of y. For a gradient greater than one, for every x increment, there have been several changes in the y value. So you will skip some values using my code, as it only ever implements x stepping.

I accidentally just forgot to write the second half of the code...

By doing 1/gradient, and incrementing by y, you are essentially flipping the standard straight line equation from y=mx to x=y/m (or x=[1/m]y)by dividing both sides by m. you would need to change a few of the calculations, for it to work properly for y stepping, but it would definitely work.

The Bresenham algorithm is supposedly one of the most efficient ways of doing it, because it keeps clear of using double values and uses ints instead. I haven't looked into how the Bresenham algorithm works, but if I were a beginner, I would use whatever made sense to me the most, because copying and pasting code when you don't understand it and couldn't rewrite it yourself is usually a bad habit to get into.

Well, if you want the basic premise for my code, so you can modify it to work for you/rewrite it, this is the basic idea i used:

1. Calculate the gradient and set one of the ends of the ray to be the graph origin.2a. Stepping through the x coordinates, use the equation y=mx (where m is the gradient) to find the corresponding y value.2b. take the x value and the calculated y value and check to see whether that tile is blocked2c. If the tile is blocked, it is not possible to light the final tile2c. If you have reached the final tile, it is possible for the light to travel this path3. Repeat steps 2 until all tiles in the possible area have been checked.

That sounds simple, but it looks a bit more of a pain in the arse in practice... Anyway, thanks for all the help, after I've changed my map system from an array of buffered images... I'll have a go at it, then post my results

Basically, like the one I showed, what you have coded there only works for 1/8th of the possible lines, you need to scroll down a bit on the page to learn what to change for the others. It is very similar to the first one, but just has a few signs changed and the like.

Also, would you mind explaining why you are accessing map tiles in that array, by minusing and dividing and casting?

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