Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

357 Neutral

About olgalatepu

  • Rank

Personal Information

  • Interests
  1. olgalatepu

    Faking 2D Shadows

    Oh yeah, such a nice city in the summer, we could talk game development and watch the students in miniskirt pass by..
  2. Alright, that makes sense. I'll try to find some time to improve it then
  3. Introduction You'll find many other articles online about collision detection, so why write yet another one? First of all, because I want to, and second because I wish that when I was starting do learn this stuff, somebody would have told me that working in layers would make my life so much easier. Collision detection which is the real topic of the post is only one of the things that is made simple thanks to the layer approach. Detecting collisions Dividing your scene in layers is something totally conceptual, you don't "need" to do it. However I find that it makes things simple to divide up your game world into groups of similar objects and to paint and update them independently. So how is this going to help us detect collisions? Well, thanks to this layered approach, we're going to skip spatial indexing, Separating Axis Theorem, and other things that are all hard to implement correctly. Let's start with two layers, the first layer contains a monster while the second contains an obstacle. Since these layers will be drawn independently, we will end up with a bitmap containing our obstacles and one containing the monster. We'll later draw them on screen sequentially We'll select a restricted number of pixels around the monster to probe the bitmap containing the obstcles on front of him. If a pixel position is not transparent in the "obstacle bitmap" we have collision! Since the obstacle bitmap acts as a spacial index, we don't need to build one ourselves and since it's a map, the entire operation is constant time. The probe pixels where crudly set in a semi circle around the monster because it always moves forwards and a circle is a suficient aproximation for this particular 2D game. Responding to collisions The probe pixels are set at a specific angle around the monster meaning that based on what probes are activated, we can calculate the collision angle, more or less precisely depending on how many probes we have. The collision angle is an approximation that we could improve by having more points but again, performance, general apearance and ease of implementation will take priority. in response to the collision, we want to give the monster a push at an angle which is the reflection of it's speed relative to the collision. Where the collision response vector is given by: response = speed - 2(dot(speed, normal)) x normal Interesting Points In this example, the monster always move forwards but if the collision angle is at an obtuse angle with the speed vector (something hitting it from behind). we'll need to change the collision response a little. I beleive we can get away with simply inverting the collision normal but I haven't tried it out to be honest. Another thing to look out for is that the collision response should be at least a little stronger than the force pushing towards the collision, otherwise, the monster would slowly sink into the obstacle. Conclusion What I mostly want to share is that viewing and coding your game in layers will give you a lot of flexibility for game development, it's part of building a propper MVC architecture.
  4. olgalatepu

    Bringing World War and Communist Propaganda Back to Life

    I love the sentence, "Lacking artistic skill and budget can lead to some creative solutions", it's truly inspiring! The result looks really good, I wonder what other style of art is in the public domain.
  5. olgalatepu

    Faking 2D Shadows

    Haha, there are others.. but yeah, Luciad
  6. olgalatepu

    Faking 2D Shadows

    Introduction The technique presented here runs at 60 fps on a decent android phone (one+3). and more than 30 fps on my old nexus 7 (2012). The main advantage of the technique are great looking soft shadows with minimal development effort. The code was written for android and renderscript but the concepts are so simple it'll be easy to port to anything else. Just fake it! The idea here is that we're not going to get into any complex calculations or mind-bending projection of our game world, we're just going to fake it. The algorithm isn't "pixel perfect", it's essentially a hack and it's probably not the fastest technique but the advantages definitely outweigh the drawbacks for quick and small projects. Base concept The concept is to paint every shadow-caster in black several times with increasing scale, Apply some blur and you're done. By tweaking the bluring and the scaling steps, you get something like the pictures below. This looks pretty good when the light-source is far away from the shadow-caster but when it's close to it, the shadows don't extend very far. we can extend the shadows further by adding more shadow painting passes but the algorithm becomes costly while if we increase the scaling steps, artifacts become apparent. Still, this approach has great looking soft shadows and the shadows are actually correct for a light-source floating a little above the screen. The other advantage of the approach is that it's independent of the number of shadow-caster objects you have on screen, so unlike in a ray-casting approach, you don't need any spacial indexing and collision detection work. An improved approach The problem with the algorithm above was that we need multiple render passes for longer shadows, making things really slow, especially on a phone or tablet. The idea is to paint the shadow-casters once in black and then for each pixels, to advance in steps towards the light until a black pixel is encountered. In the picture below, pixel A will be in the shade while pixel B will be in the light. The risk is that by using a large step size, we may step over a shadow caster, so we'll need to adapt our step-size depending on the size of shadow-casting objects. Optimization The most important optimization to keep in mind is that the shadow computing pass and the blurring pass should always be done on a scaled down image. We can also hardware accelerate the work. The following bit of code is a RenderScript script (Android exclusive) that will run on every pixel on an image where shadow-casters are painted in black, and every other pixel is transparent. #pragma version(1) #pragma rs java_package_name(com.olgames.hideandeatbrains.painting) //these variables are set directly from java code. float light_x; float light_y; float stepSize; // The input allocation is a copy of the Bitmap, giving us access to all the pixels of the bitmap. rs_allocation input; // out contains the currently processed pixel while x and y contain the indices of that pixel. void root(uchar4 *out, uint32_t x, uint32_t y) { // First get the current pixel's value in RGBA. float4 pixel = convert_float4(out[0]).rgba; // if the current pixel is already drawn to, we can early exit. if(pixel.a>0.f) { return; } // We'll increment this variable as we go. float currentStep = stepSize; // We need to calculate the distance to the light in order not to step past it. float dX = x-light_x; float dY = y-light_y; float dist = sqrt(pow(dX,2)+pow(dY,2)); // we loop and check for "collision" until either we collide or until we step past the light. // if we collide, we set the current pixel to black. while(dist>currentStep) { float4 in = convert_float4( rsGetElementAt_uchar4( input, floor(x-((dX/dist)*currentStep)+0.5f), floor(y-((dY/dist)*currentStep)+0.5f) )).rgba; if (in.a >0.f) { pixel.r=0; pixel.g=0; pixel.b=0; pixel.a = 255; out->xyzw = convert_uchar4(pixel); break; } currentStep+= stepSize; } } We'll still need to apply blurring. RenderScript offers very efficient API for that purpose on android. Conclusion I almost gave up on implementing shadows for my androidgame because I simply did not have the time to implement more complex algorithms. This technique can be implemented in a few hours. I sincerely hope this will be useful to some of you. Article Update Log 1 Feb 2017: Initial release
  • 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!