Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411314 Posts in 69330 Topics- by 58383 Members - Latest Member: Unicorling

April 03, 2024, 02:43:45 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
  Show Posts
Pages: 1 ... 11 12 [13] 14 15 ... 18
241  Community / Tutorials / 2D Shadow Effects on: October 25, 2009, 10:11:03 AM
What's this about?
The aim is to produce shadow effects for 2D games in realtime.  A notable example of this in action would be Gish or Hitlers Must Die.  Sadly I have nothing to do with the making of those games though.

A demo of what we'll be making:


Click to go to an interactive version.


I do most stuff with Flash so I'll use Actionscript during this, but the principles are general and it could be applied to whatever you like to work with.  If you've never met Actionscript you'll be able to read it just fine.  I also make use of Box2D's b2vec2 class in some example code.  Again no need for you to be familiar with it; it's a pretty standard class to deal with 2D vectors.

The aim of this tutorial is to explain the concepts in use by means of prose, diagrams and code.  It'll not give you a finished shadow-drawing engine at the end but it should teach you how to make one yourself, and that's much more fun!

Casting shadows from polygons
Before we can draw the shadow coming from a shape, we need to have the shape represented somehow.  Polygons are a good way to do this - it means we represent the shape as a series of connected lines that form a solid 2D shape.  The demo above shows a crowd of regular polygons, but it'll work just as well for irregular and even concave polygons.  Plenty of games aren't limited to just geometric shapes, but as with collisions and physics it is often useful to simplify shapes to an approximate polygon.

How you store these polygons is something I'll leave up to you as it will depend a great deal on what libraries you're using or what else you have going on in the game.  For instance re-using the shadow-casting polygons as collision-detection polygons will often work out as a good solution.  In the demo I have used Box2D to handle the physics, so have also used its own representation of the polygons.

Whatever shape our polygon is and however you represent it in code, it'll be constructed of straight lines.  The good thing about straight lines is they're nice and simple.  So we'll do the shadow casting on individual lines, and build those up into a shadow for the whole polygon.

Shadowing a Line
Here's how we want the shadow from a single line to look, with the orange circle as the light source, and red line as the shadow casting line:



So our task becomes drawing the shape of the shadow, which is given by the points A, B, C, D.  Points A and D are already known as they're just the start and end of the line.  B and C are quite easily found:

Think of point B as being point A after being moved.  But what direction to move it?  Easy!  Apply the same movement as would be needed to get from L (where the light source is) to A.

To put it in more mathematical terms:
Take the vector L-to-A, and add it to the position vector of A.

To put it in code terms, using the b2vec2 class from Box2D:

Code:
private function projectPoint(point_:b2Vec2, light_:b2Vec2):b2Vec2
{
var lightToPoint:b2Vec2 = point_.Copy();
lightToPoint.Subtract(light_);
var projectedPoint:b2Vec2 = point_.Copy();
projectedPoint.Add(lightToPoint);
return projectedPoint;
}

Of course the very same process can be used to find point C from D.

Drawing out the resulting shadow is a simple enough process.  Using the .graphics methods of a shape object for instance:

Code:
var shadows:Shape = new Shape();
var projectedPoint:b2Vec2;
shadows.graphics.lineStyle(1, 0, 0);
shadows.graphics.beginFill(0, 1);

shadows.graphics.moveTo(startVertex.x, startVertex.y);

projectedPoint = projectPoint(startVertex, light);
shadows.graphics.lineTo(projectedPoint.x, projectedPoint.y);

projectedPoint = projectPoint(endVertex, light);
shadows.graphics.lineTo(projectedPoint.x, projectedPoint.y);

shadows.graphics.lineTo(endVertex.x, endVertex.y);

shadows.graphics.endFill();

Just repeat this process for every line in every polygon, and you'll have the full shadow of the shapes drawn out.  Done!  Fantastic!

A first optimisation
Now that it works, we can start on the long road of making it faster.  If you look carefully at the shadows in the demo you can see that only the lines that are facing away from the light actually influence the shape of the final shadow.  This means that we're processing and drawing the shadows for many lines which we don't actually need to.



Here a shape (shown in red) has shadows cast thanks to a lightsource.  See how the shadow lines that I have coloured a lighter grey fall entirely within the larger shadow, and so will not affect the final shadow image?  We've spent precious time drawing out those shadows, but the player never actually sees the result - what a waste!

The good news is that it's simpler than you might think to determine if it's worth drawing the shadow from a line.

You might notice that it's the lines facing towards the lightsource that we don't need to draw shadows from.  Using a little vector maths we can quite easily find which lines are facing the lightsource, and so which are worth drawing shadows for.

You can consider each line as splitting the world into two parts: the world on the left of the line and the world on the right.



Take note that which side is left and which is right will depend on the direction you're considering the line from.  So make sure you always consider the lines of your polygons as going from one point to the next along in a clockwise direction (or counterclockwise if you like - just be consistent.)

In this case we're going clockwise, and we can see that for this particular line the lightsource falls on the left hand side.  Check the other lines, and you'll find that only lines where the lightsource falls to their right will cast a shadow that actually needs to be drawn.

We can use a little bit more vector mathematics to determine if the lightsource is to the left or right of any particular line:

First we find the normal of the vector that goes from the start to the end of the line, then take the dot product of that and the vector that goes from the lightsource to the start of the line.  The dot product will be a number, but we're only interested in if it's positive or negative, as that will indicate what side the lightsource is on.

I'll not try to fully explain the vector maths that just happened, but I'll give a taste.  The normal of a vector is a vector that is at right-angles.  It's very easy to find - just swap around the x and y components of the vector, and multiply one of them by -1.  Which one you multiply by -1 will determine if you get the normal that points to the left of the vector or to the right.  Taking the dot product of two vectors gives us a number (not a vector) which can be used for other clever things, but for now all we're worried about is that it is positive if the two vectors point in the same direction, and negative if they point away from one another (and zero if they're perpendicular.)

Effectively we are drawing a new line at right-angles out of the line we're considering, and asking if it points towards the light source.  If it does, we know not to bother drawing the shadow for this line.

In code:

Code:
private function doesEdgeCastShadow(start_:b2Vec2, end_:b2Vec2, light_:b2Vec2):Boolean
{
var startToEnd:b2Vec2 = end_.Copy();
        startToEnd.Subtract(start_);

        var normal:b2Vec2 = new b2Vec2(startToEnd.y, -1 * startToEnd.x);

var lightToStart:b2Vec2 = start_.Copy();
lightToStart.Subtract(light_);

if (dotProduct(normal, lightToStart) < 0)
{
return true;
}
else
{
return false;
}
}

private function dotProduct(vecA_:b2Vec2, vecB_:b2Vec2):Number
{
return (vecA_.x * vecB_.x + vecA_.y * vecB_.y);
}

End
There's still plenty more to cover on the topic; off the top of my head:
Using BlendMode to make shadows be shadows instead of black voids (which is slightly more Flash-centric, although I'm sure you can get the same effect with OpenGL)
Different ways to determine the length of shadows.
Creating a "torch beam" effect.
Dealing with multiple and coloured light sources.
General graphical consistency considerations.

I hope someone will find this part useful at least.  Questions, comments?  What part was hardest to understand?

If you like, the source for the simple example is available here. There's a FlashDevelop project in there, but the important stuff is just two .as files that can be opened in any text editor. It uses Box2D for the shapes, so if you're not familiar with that then the source may be needlessly confusing.
242  Community / Tutorials / Re: Braving Procedural Generation [ Part Three! ] on: October 06, 2009, 05:47:33 AM
Threads I've found:

This one.  Which I see as being about algorithms for generating levels.  Primarily open landscape maps (mainly based on heightmaps) and cave maps.  Although there are mentions of other procedural generation possibilities (stories/histories like Dwarf Fortress'.)

One in the Design forum that newton64 just linked.  That's focused around an attempt by Mephs to prototype a game that procedurally generates objectives as well as general content (I think.)  Plenty of interesting talk about combining mechanics to get fun results, and the danger that too many random elements poses on difficulty.

Again in the Design forum.  This is concentrated on generating levels/maps, but also discusses the "tinker toy" approach, of slotting together pre-made parts (much like how Spelunky generates its levels.)  Sadly the thread stops just when 'full-on' procedural generation of platformer levels is brought up.

Then of course there's all of the PCG Compo.

--
On the issue of generating obstacles rather than generating pretty levels, I have something to contribute!  I'm working on generating the layout of a game world with basic lock-and-key obstacles.  You can read words, and watch a simple level being generated here.

My aim currently is to keep it as abstract as possible, so the key could be replaced by "ability to morph into a little ball" and the locked door with "a tunnel too small to walk down."  And suddenly it's generating the layout for a Metroid game.
243  Community / DevLogs / Re: VERSNOOF on: October 05, 2009, 03:43:25 AM
For 'remembering' past floors, you've two options really:

Either store a seed number for each floor (which could be randomly generated when a new game is started.)  That way each time you enter a particular floor the game looks up that floor's seed number in a nice simple list, and generates the floor fresh.  So long as the procedural generation of the floor occurs "all at once" and with the just-seeded random number generator it'll always produce the same thing.  The problem is that it'll also produce the same treasure and enemies as the first time the player entered.  So you may want to maintain a list of which treasure items have been picked up for each floor, and remove those from the map once it has been generated (unless you're happy for there to be respawning treasure of course.)

The other option is to generate all the floors at the start, and just store them in some big level data storage thing.  I've no idea how that would work with GameMaker's built in level handling stuff.
244  Player / Games / Re: Which indie games have you spent the most time playing? on: September 25, 2009, 11:59:33 AM
Much like the OP, Liero in free time back in high school probably added up to a lot.

More recently, Dwarf Fortress and Spelunky are the only indie games I've really put a lot of time into playing.
245  Developer / Playtesting / Re: FLOATILLION on: September 21, 2009, 01:06:16 AM
So, are there more controls than just the right cursor key?

The music varies wildly over time, and I want to change the vertical position of God so I can reach more happiness balls.  I assume there must be a way, or else this is a FUNNEH TROLL game?  I'm not given any clues and short of mashing 110 keyboard keys hoping something works, I don't have a starting point for working it out.  So I'm afraid I just gave up, sorry.

The art style is lovely though.
246  Community / Townhall / Re: Maggot Blaster 500 on: September 17, 2009, 06:20:07 AM
Gentle bump to say that I've found a sponsor, and Maggot Blaster can now be played!  On the internets!  Just on the sponsor's site for the first week.

Hope you don't hate it.

Also, posting this made me notice that Time Fcuk is released!  Most excellent!
247  Player / General / Re: How do you start running the Spelunky game? on: September 17, 2009, 04:38:37 AM
Have you unzipped every file in the Spelunky.zip archive to the same folder on your computer (e.g. C:\Games\Spelunky) before running the exe?

I'm guessing this is the culprit. What's the default for whatever the native Windows unzipper is? Does clicking on the zip open the zip or extract it?

It opens the zip, in a window that looks just like a normal directory.  Smart 'eh?  There is usually a warning saying that you might like to extract stuff first if you try to run an .exe from there though.
248  Developer / Technical / Re: Incorporating 'premade' movieclips into a FlashDevelop project? on: September 16, 2009, 02:05:29 PM
Much success!

I had two premade things to incorporate into my game (as part of a sponsorship deal to add branding.)  First was their preloader which was very fluffed up with animations and voice-overs(!), second was their online high-score system.  Both were made in Flash 8 with AS2 code.

I probably could have re-written the AS2 code of the preloader into AS3 to make things a bit simpler, but the mass of code for the score system would have taken a whole lot of work.

Connections I ended up using:
Game to preloader - informing the preloader how much of the game had loaded, so it could update its progress correctly.
Preloader to game - announcing when its various animations had finished so the game knew when to hide the preloader and start up.
Scoreboard to game - requesting to know the player's score.
Game to scoreboard - passing the score over in response to the above request.

To make those connections work I had to fiddle with the preloader and score system's code a little, but nothing too traumatic.

This was also my first time in years using the 'real' Flash IDE (I downloaded the CS4 trial for it,) and it reminded me very well why I used FlashDevelop instead.  The code seems to be so spread out and hard to find!  It annoys me a little that I'm likely going to have to buy Flash CS4 just so that I can do similar fiddling for future games.  I guess it'll be useful for general vector graphics work, or as an easy level editor.

Thanks again!  Saved me.
249  Developer / Technical / Re: Incorporating 'premade' movieclips into a FlashDevelop project? on: September 15, 2009, 03:37:22 AM
Salt you need to embed it like you're already doing, then to communicate with it you can use "LocalConnection" http://www.flashvalley.com/fv_tutorials/localConnection/

It is actually starting to work!  I have a message being sent by the AS2 logo saying when it's done animating, and it's being successfully picked up by the AS3 game.  I still need to make it actually do useful stuff, but I have a starting point now.

Thank you so, so much.
250  Developer / Technical / Re: Incorporating 'premade' movieclips into a FlashDevelop project? on: September 15, 2009, 01:05:18 AM
I can kind of embed the logo:
Code:
public class newLoader extends MovieClip
{
[Embed(source = 'LOGO - flash8.swf')]
private var testCls:Class;
private var logo:MovieClip;

public function newLoader()
{
logo = new testCls();
addChild(logo);
}
}
That causes the logo to be displayed and play through, just as though I'd opened it alone in the Flash Player.  I seem to have no way of telling what is going on 'inside' the logo.  I have heard about the AVM1Movie class which is meant to handle (very limited) interaction with AS1.0 and AS2.0 movieclips, but I seem to only be able to declare my 'logo' variable as type MovieClip, not AVM1Movie. Shrug

Currently downloading the Flash CS4 trial; maybe I'll be able to pull everything together in there somehow?  Having never used it before, any hints on getting from a FlashDevelop project to a Flash IDE project?
251  Developer / Technical / Re: Incorporating 'premade' movieclips into a FlashDevelop project? on: September 14, 2009, 04:37:37 PM
I'm starting to understand what my problem actually is.  Which is a start!

I have a game, written in Actionscript 3.0 targetted at Flash Player 10.  The game exists just as a collection of actionscript files ready to be compiled.  Notably, there's no .fl file for the game.

I have been given a pretty animated logo, with some basic code.  This logo's code is Actionscript 2.0, and it's made for Flash 8.  I have access to the .fl file for this logo, so can make some changes to the code if I need to.  The behaviour of the animated logo is to display a pretty animated bar as the rest of the flash movie it is in loads, then hand over to the actual game.

I also have some high-score thing, but sheesh forget about that for now.

Hopefully I'll be able to get in direct contact with "the programmer guy" tomorrow, but I've no idea if he'll be any help.


It seems that what I want to do is embed this old-version Flash movie within my game, and then pass some information and actions between the two.  I have utterly no idea how to do that!

I already have an ugly home-made preloader working.  Made just in AS3, that updates a loading bar as the stuff downloads.  So I have the functionality, I just need to pass that over to this antique logo.

My attempts at embedding have so far resulted in hearing the sound effects from the logo, and then the flash player hanging.  Hohum!
252  Developer / Technical / Incorporating 'premade' movieclips into a FlashDevelop project? on: September 14, 2009, 12:21:10 PM
Hi!

I'm trying to stick a sponsor's preloader in my game.  They've provided it both in .fl and .swf format.  Their preloader is made so that once it detects everything has loaded and done all its own animation stuff, it will make its parent clip play (which should be my game.)

But.  I have no idea how to do this with my game existing as just a bundle of actionscript files in a FlashDevelop project (being compiled by mxmlc.)  I found an ancient copy of the Flash 8 IDE, which is able to deal with the preloader's .fl file.  But my game relies on Flash Player 10 features, so I guess I can't just stick it into a 'real' Flash file?  I'm at a loss.

I know there's a handful of others around here who are making things in Flash with just FlashDevelop, I wonder if you've dealt with similar things?  Thanks very much!
253  Developer / Technical / Re: The Experimental Technology Thread on: September 12, 2009, 09:08:23 AM
Kind of similar to the "pacman scent" in that antiobjects example: Pathfinding for many units by having them share a global distance-from-target map.

Basically you use your processing time to generate a value for each tile in the game indicating how far it is from the target (taking into account obstacles,) then have the units blindly follow that map - which is a computationally simple task.  The upshot is that computation time increases very little when you increase the number of units following the map.  I just so happened to have recently written up how I've used this.


Seam Carving for Content-Aware Image Resizing, this is just an amazing idea, watch the video.
That is extremely excellent.  As is this whole thread in fact!
254  Developer / Technical / Re: Vectors? on: September 09, 2009, 05:03:52 PM
Going back to the original question:

Once you make a vector graphic in inkscape and save it as a .svg file, you can use it in your code like so:

Code:
public class main extends Sprite
{
   [Embed(source = "prettyPicture.svg")]
   private var myPictureCls:Class;
   
   public function main()
   {
      var mySprite:Sprite = new myPictureCls();
      addChild(mySprite);
   }
}

the [Embed...] line followed by the declaration of a variable of type Class is the standard way to embed things without the Flash IDE.

Weird little things I have found using this method:
Don't use gradients in Inkscape - they don't get imported into your program properly.
Don't use alpha values in Inkscape - it does bizarre things when you try to import it.

It's not nearly as convenient as using the Flash IDE, but it is easier than trying to use the .graphics stuff to draw complex forms.

For the second question, I'm not sure why there would be such a slow down from just drawing a circle every frame.  Maybe post your full code here?  It certainly sounds like there's something freaky going on somewhere.
255  Developer / Business / Re: Flash Game License on: September 02, 2009, 03:28:46 PM
Fresh updates in the form of a timeline, with each line as one day:

- Put game up
-
-
- Bid from A for $500
-
-
-
-
-
-
-
-
-
-
- Bid from B for $700
-
-
-
-
-
- Sent out a load of direct contacts to sponsors
-
- Bid from C (one of those I contacted directly)  for $800
- Bid from B for $1000
- Bid from C for $1100
- Bid from B for $1200
-
- Bid from D (not someone I contacted directly) for $1400
- This post


Just getting enough sponsors to see it seems to have been the key so far.  B must have thought he/she was on to a bargain until C turned up.

Bidding is sitting in the range that would cover my living expenses for the development time, so I'm pretty comfortable now.  I will wait at least another week to make sure there's no more fresh sponsors waiting to appear.  I've been ticking off the list of sponsors I contacted when I see them appear on FGL's 'viewers' list. I also gave the sponsors a secure link outside of FGL in case they didn't have a sponsor's account there, so I can't tell which specific sponsors have viewed it there.
256  Developer / Business / Re: Week 2 of working in the industry on: August 29, 2009, 12:47:04 PM
It really does violate labour laws.

Minimum wage in the UK for anyone over 22 is £5.73 an hour (£4.77 if you're 18 to 22.)  Only way you can pay someone less than that is if they're on an apprenticeship scheme (and that means actually being on an apprenticeship scheme, not "it's kind of like being an apprentice.")

You can submit a complaint to the government online if you like:
http://www.hmrc.gov.uk/nmw/complaint.htm

Either way, get outta there.
257  Developer / Business / Re: Flash Game License on: August 29, 2009, 12:31:07 PM
Goddamn zombies, ruining it for everyone.

I figure changing the name now would mostly just confuse all the people I've contacted asking to check it out.  I did change the "short description" field on FGL.com to hopefully better reflect its strategic interest.  My standard email I've been sending out directly describes the game as being in a similar vein to SAS Zombie Assault, so hopefully they can get a picture of what the game's about (and  Hand Money LeftCrazyHand Money Right) pretty fast.

Good news is, I've got a reply back from one of the sponsors I contacted directly and the bidding is up to $800! $900! $1000!  Not a vast increase, but this is a standard duration bid so I have a lot more breathing room for more sponsors to see it.  My previous highest bid was going to expire in less than a week, which was making things feel a bit rushed.

Thanks a great deal for all the support!
258  Developer / Business / Re: Flash Game License on: August 28, 2009, 09:59:44 AM
Thanks a lot everyone!

I've spent today re-jigging the interface slightly so sponsor logos have space to go (and put placeholder logos in there,) and sending out contacts directly to sponsors.  Still have more emails to send.  Wish me luck!

I totally agree that selling the game is turning out to be more work than making it.  My consolation is that once it is sponsored, it'll be free for the player and I'll not starve.
259  Developer / Business / Re: Flash Game License on: August 27, 2009, 04:56:42 AM
Hi!  I have a very similar question to the start of this thread, so I guess it's okay to re-use it?  Seems better than burying the nice useful posts here.

My game's been on FGL for two and a half weeks, and has got two bids.  Hurray!  I find myself hesitating to accept the higher bid - can your combined experiences help tell me if I'm right to?

The game:
Amusingly, rather similar to I MAED A GAEM WITH ZOMBIES IN IT!!!11 but without the irony, longer, and actual maps rather than the open field aesthetic of most Crimsonland clones.

I have a hard time judging its worth.  It took me two months to make, but it could just as well have taken three months if I'd worked (even?) slower.  It's my first 'real' finished game in Flash, so a lot of that development time was learning things.

When it was approved for sponsor viewing by FGL, it was given an editor rating of 8/10.  I have not much idea of what that means - is this using the magazine review scale where 7 is the worst game ever, and nothing gets a 10?  Sadly editor ratings on other games are only shown to sponsors, so I've no idea how I match up.

If you have a FGL.com account, you can play it (if it doesn't give you access let me know and I'll add you as a friend): http://www.flashgamelicense.com/view_game.php?game_id=6954

You can also see a brief video/trailer:



The bids:
$500, then $700.  The $700 bid has quite a short time limit on it, so I'm a little rushed to make a decision.  Both bids are for primary licenses and allow me to add in-game ads.

The worry:
It seems like it has got quite little exposure to sponsors.  Am I totally off in my estimation of how viewed it should be?  FGL.com provides a list of who has viewed the game, which shows that 8 sponsors have tried it in the 17 days it has been up.  Of those 8, 2 have placed a bid, which feels like a decent 'conversion' rate to me.

Should I keep it up for a few more weeks and let the $700 bid expire, hoping that more sponsors will see it and like it?

4 days ago I put that trailer together and submitted it to a FGL person who is maintaining a page of trailers for games in active bidding (an automated email from when the game was approved for sponsorship viewing encouraged the creation of a trailer.)  I've got no word back on if they're doing anything with it.

I'm keen to get this game sold off and done.  But I'm also keen not to be totally ripped off.  Painfully honest advice would be greatly appreciated.  Thank you!

Bonus question!
Both bids specify CPMStar ads.  I've only had experience with MochiAds previously, any opinions on CPMStar?  A brief trawl of the internet gives the impression that CPMStar ads are smaller and easier for the player to skip, and pay out when the player actually follows through on the ad rather than just views it.
260  Community / Townhall / Re: Maggot Blaster 500 on: August 24, 2009, 05:45:53 PM
Thanks guys  Smiley

I've been slightly stressing myself out over it.  I recently graduated from university (with a not terribly career-applicable degree in Philosophy and Cognitive Science,) and am really hoping I can make a living off doing what I love.

I keep working out what income I'd need from a game that took two months to make in order to afford a studio flat for the same time, which probably isn't wise.  Hopefully I'll keep getting faster and better at working on games so it'll get easier.  At the least, I could make another top-down shooter very rapidly.  Maybe one with zombies!

A thread on TIGS means this game is officially finished, so I can settle down to my next project: A one-level-per-screen physics platformer with a twist of self-immolation.
Pages: 1 ... 11 12 [13] 14 15 ... 18
Theme orange-lt created by panic