tag:blogger.com,1999:blog-6481734144428457572024-03-19T00:03:40.908-05:00Super ObeliskDevelopment log for 'Super Obelisk', a game that I'm making.Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.comBlogger62125tag:blogger.com,1999:blog-648173414442845757.post-18618919006503323152013-12-05T00:11:00.003-06:002013-12-05T00:12:17.875-06:00Videos from a Rainy Area<br />
Oh, hey? Yes, I'm still here. Yes, I'm still working, and yes, there are more videos. Hope you enjoy these and the progress so far!<br />
<div>
<br /></div>
<div>
<br /></div>
<div>
Hiding stuff in a bush:</div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/GSzlbUbdi9M?feature=player_embedded' frameborder='0'></iframe></div>
<div>
<br />
<div>
<br /></div>
<div>
Having fun with bushes:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/V3cNyIfSJWk?feature=player_embedded' frameborder='0'></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Obelisk Mode. Note, this is just for demo purposes, the game won't work with 'portals' like this.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i1.ytimg.com/vi/s4D_9nqy6OQ/0.jpg" height="266" width="320"><param name="movie" value="http://www.youtube.com/v/s4D_9nqy6OQ?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/s4D_9nqy6OQ?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Moving up and down. Going through 'warp doors' and jumping off cliffs.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/Q1V-vAnBKas?feature=player_embedded' frameborder='0'></iframe></div>
<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
</div>
</div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-90887350935603968562013-11-10T01:35:00.002-06:002013-11-10T01:36:07.319-06:00Hard at WorkOkay, you've probably caught on now: I have been too busy actually working on the game to give super detailed updates on this blog. Hopefully you've enjoyed the development videos I've been posting, because for the time being that's what I will continue to post.<br />
<br />
Here's the last few video I've put together that show my progress:<br />
<br />
<b>1. Super Dash</b><br />
<b><br /></b>
I'm testing out an ability which lets the player go <i>really </i>fast.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/jMap6rzxyIo?feature=player_embedded' frameborder='0'></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>2. Step Triggers</b></div>
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: left;">
These are switches that you activate by stepping on a switch on the ground.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i1.ytimg.com/vi/gyoadUE_40s/0.jpg" height="266" width="320"><param name="movie" value="http://www.youtube.com/v/gyoadUE_40s?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/gyoadUE_40s?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<b>3. Delay Triggers</b><br />
<b><br /></b>
A special entity that simply delays a trigger and then relays it to the next one. Good for sequenced events.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/Vp10N6CETeE?feature=player_embedded' frameborder='0'></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>4. Idle Animation</b></div>
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: left;">
Allison put together a nice idle animation for the main character.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div style="text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i1.ytimg.com/vi/QpGOO_E_0XU/0.jpg" height="266" width="320"><param name="movie" value="http://www.youtube.com/v/QpGOO_E_0XU?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/QpGOO_E_0XU?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: left;">
<b>5. 3-hit combat demos</b></div>
<div style="text-align: left;">
<b><br /></b></div>
<div style="text-align: left;">
Playing with a simple 3-hit combo system.</div>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i1.ytimg.com/vi/i9Dua_X0vUA/0.jpg" height="266" width="320"><param name="movie" value="http://www.youtube.com/v/i9Dua_X0vUA?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/i9Dua_X0vUA?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
...same thing, experimenting with variable knockback forces. Also we've started prototyping a new environment.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/l6XUg26YTrk?feature=player_embedded' frameborder='0'></iframe></div>
<div style="text-align: left;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-69457210343963542792013-10-22T00:08:00.002-05:002013-10-22T00:08:29.581-05:00More Video UpdatesLately I've been moving. Not much time for blog posts, but I've still got some work to show! More videos!<br />
<br />
1. First up: falling down transitions. I wanted to put a little twist on the fade out / fade in 'falling' transition. This was the first draft:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<object width="320" height="266" class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i1.ytimg.com/vi/d2wZ_wrlGGA/0.jpg"><param name="movie" value="http://www.youtube.com/v/d2wZ_wrlGGA?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/d2wZ_wrlGGA?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<br />
2. After some feedback, here's what I ended up with as a final draft. Way better.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/mRD0e3oPU6Q?feature=player_embedded' frameborder='0'></iframe></div>
<br />
3. Just for fun, I added some bugs.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<object width="320" height="266" class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i1.ytimg.com/vi/EfkYc_gEqw0/0.jpg"><param name="movie" value="http://www.youtube.com/v/EfkYc_gEqw0?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/EfkYc_gEqw0?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<br />
4. Some people suggested that the bugs shouldn't be squished when you're holding still. Someone else took it further and said that they should climb up you. So I did that.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/5gN3Cm8MNCY?feature=player_embedded' frameborder='0'></iframe></div>
<br />
Stay tuned for more!<br />
<br />Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-39563736944866257332013-10-07T23:21:00.000-05:002013-10-07T23:31:16.855-05:00Lots of Fun Development Videos<div>
Although I haven't been updating this blog as regularly as before, it's only because I'm too busy with the actual game programming it self. I'd like to share a few videos that I've created over the past month or so.</div>
<div>
<br /></div>
<div>
I keep fairly active on twitter, so follow me at <a href="https://twitter.com/ericswheeler">https://twitter.com/ericswheeler</a></div>
<div>
<br /></div>
<div>
<b>1. The Chasm</b></div>
<div>
<b><br /></b></div>
<div>
Just a fun little demo of dynamic floor tile scripts.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/AIUsHUpX9Ow?feature=player_embedded' frameborder='0'></iframe></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<b>2. Persistence</b></div>
<div>
<br /></div>
<div>
Here's a video where I demonstrate values persisting between level loads. When the bridge spawns, the player can leave the screen and come back and it will still be there.<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/oG62-i3WhYE?feature=player_embedded' frameborder='0'></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>3. Dashing and Torches</b></div>
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: left;">
In this video, I've swapped out the old (temporary) character art for a new (also temporary) sprite that represents the actual dimensions of the character. We chose a large head so that the player can fit in a more square-like area because we want the visual appearance to be close to the collision box, so the player can gauge whether or not something is going to collide with the player. This video also features dashing and dash-turning. And some fireballs. And a shield.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/CRg-HSzXQIM?feature=player_embedded' frameborder='0'></iframe></div>
<br />
<div>
<br /></div>
<div>
<b>4. Switches</b></div>
<div>
<b><br /></b></div>
<div>
Implemented some switches. You can also see the design of the main character taking shape. One of the switch types is a basic toggle, the other is timer-based.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/rT6OukJRVzg?feature=player_embedded' frameborder='0'></iframe></div>
<div>
<br /></div>
<div>
<b>5. Fog</b></div>
<div>
<b><br /></b></div>
<div>
A cool fog effect.</div>
<div>
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i1.ytimg.com/vi/ZS-qGuEkN_U/0.jpg" height="266" width="320"><param name="movie" value="http://www.youtube.com/v/ZS-qGuEkN_U?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/ZS-qGuEkN_U?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<div>
<b><br /></b></div>
<div>
<b>6. Doors</b></div>
<div>
<b><br /></b></div>
<div>
A set of switches that controls the opening and closing of a door.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/Rr6fbzvISVQ?feature=player_embedded' frameborder='0'></iframe></div>
<div>
<b><br /></b></div>
<div>
<b>7. Section entry events / group destroy triggers.</b></div>
<div>
<b><br /></b></div>
<div>
This final video shows how something can occur when a room is entered (the door is closed) and how destroying a group of tagged entities (3 blobs, in this case) can trigger something else (door opening, wall torches being lit, fog fading away.</div>
<div>
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i1.ytimg.com/vi/4oQknBn_D3Q/0.jpg" height="266" width="320"><param name="movie" value="http://www.youtube.com/v/4oQknBn_D3Q?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/4oQknBn_D3Q?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
That's it for now!</div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-32863912875083897742013-09-14T00:27:00.000-05:002013-10-08T11:38:01.179-05:00Parallax Pits and Player ProportionsI've actually been spending a considerable amount of time lately working with the artist on the project, Allison. We've been slowly nailing the style down for a number of things and anticipate future art development to become more and more rapid as we settle into a groove. Refer to the following screenshot:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguUw9r8w0uFe62kmqUYFGcv5HhyG42GA_oLGFC8VaCqqC_n23gtKDSQjDP9027W2yIrKDrA9uYwGeCgH0aEN9i9s5E7e0OdpraiS8eig1W2nKK2aO8m7sFbbPILIATqpm29S7KRdYYNRI/s1600/ss151.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguUw9r8w0uFe62kmqUYFGcv5HhyG42GA_oLGFC8VaCqqC_n23gtKDSQjDP9027W2yIrKDrA9uYwGeCgH0aEN9i9s5E7e0OdpraiS8eig1W2nKK2aO8m7sFbbPILIATqpm29S7KRdYYNRI/s400/ss151.png" width="400" /></a></div>
<br />
<br />
Anyway, here's what's new since last update:<br />
<div>
<br /></div>
<div>
1. <b>Improved cave tiles. </b>I'm not going to write too much here, but things are looking better now. We're still going to have another pass at them later.<br />
<br />
2. <b>Parallax tiles underground. </b>You can't see it in motion from the screenshot, but the underground spikes are parallaxed, meaning they give the illusion of depth by scrolling at a slower rate than the foreground.<br />
<br />
3. <b>Player proportions. </b>You're seeing a temporary placeholder sprite as we test the final dimensions of the character. The goal here was to keep the player's collision model at exactly 1x1 tile (that's 32x32 in-game units--actually, we're using 30x30 so that the player can comfortably fit between two tiles). The older character also had these dimensions, but was much taller. It's pretty important to me that the player can accurately and easily gauge, visually, the collision model of the player (so that they know when they're going to get hit by an enemy or a projectile), so the closer the character is to a 32x32 box, the better. Obviously we can't make the graphic square, though, because that would look silly.<br />
<br />
<b>4. Better stylistic lighting. </b>Since lights can be any texture we want, we chose to paint a nice cartoony glow instead of the straight gradient of the old textures.<br />
<br />
That's all for now!</div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-46815446941944901852013-08-31T16:55:00.002-05:002013-10-08T11:38:56.407-05:00Lurker!It's been a couple weeks since my last substantial blog post, so I'd like to share what I've been working on during the last week: a new monster I've tentatively dubbed the <b>Lurker</b>, but I plan on giving it a more original name in the future. Note that enemy development isn't normally going to take a week per enemy--I was busy with some personal things. On top of that, this enemy is more complex than my first enemy, the <b>Blob</b>, and required a few engine infrastructure changes to implement. I'll go over those in detail, too!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj16kQFb7nm3-EzY7nlYlYow0T19wFODUZZoatOe6YPuV0rjDNtAxTr1evC2l4bjUg2_jCprwQQUsiIa5wzJMjr0KliY9DCdKIx4FU8EQKbYOZ0KRUDdQVaRMmUVZ-JrXPvkr-wqKN_zO0/s1600/lurkface.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj16kQFb7nm3-EzY7nlYlYow0T19wFODUZZoatOe6YPuV0rjDNtAxTr1evC2l4bjUg2_jCprwQQUsiIa5wzJMjr0KliY9DCdKIx4FU8EQKbYOZ0KRUDdQVaRMmUVZ-JrXPvkr-wqKN_zO0/s1600/lurkface.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj16kQFb7nm3-EzY7nlYlYow0T19wFODUZZoatOe6YPuV0rjDNtAxTr1evC2l4bjUg2_jCprwQQUsiIa5wzJMjr0KliY9DCdKIx4FU8EQKbYOZ0KRUDdQVaRMmUVZ-JrXPvkr-wqKN_zO0/s1600/lurkface.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj16kQFb7nm3-EzY7nlYlYow0T19wFODUZZoatOe6YPuV0rjDNtAxTr1evC2l4bjUg2_jCprwQQUsiIa5wzJMjr0KliY9DCdKIx4FU8EQKbYOZ0KRUDdQVaRMmUVZ-JrXPvkr-wqKN_zO0/s1600/lurkface.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj16kQFb7nm3-EzY7nlYlYow0T19wFODUZZoatOe6YPuV0rjDNtAxTr1evC2l4bjUg2_jCprwQQUsiIa5wzJMjr0KliY9DCdKIx4FU8EQKbYOZ0KRUDdQVaRMmUVZ-JrXPvkr-wqKN_zO0/s1600/lurkface.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj16kQFb7nm3-EzY7nlYlYow0T19wFODUZZoatOe6YPuV0rjDNtAxTr1evC2l4bjUg2_jCprwQQUsiIa5wzJMjr0KliY9DCdKIx4FU8EQKbYOZ0KRUDdQVaRMmUVZ-JrXPvkr-wqKN_zO0/s1600/lurkface.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj16kQFb7nm3-EzY7nlYlYow0T19wFODUZZoatOe6YPuV0rjDNtAxTr1evC2l4bjUg2_jCprwQQUsiIa5wzJMjr0KliY9DCdKIx4FU8EQKbYOZ0KRUDdQVaRMmUVZ-JrXPvkr-wqKN_zO0/s1600/lurkface.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj16kQFb7nm3-EzY7nlYlYow0T19wFODUZZoatOe6YPuV0rjDNtAxTr1evC2l4bjUg2_jCprwQQUsiIa5wzJMjr0KliY9DCdKIx4FU8EQKbYOZ0KRUDdQVaRMmUVZ-JrXPvkr-wqKN_zO0/s1600/lurkface.png" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
I wanted to add a new enemy which will appear in the first area of the game, <b>Gloomstone Cave</b>. The idea is that you'll be facing this enemy in a few spots, but initially you won't have a permanent weapon to defeat it with. So, you must come up with more creative ways to pass the first few of them, whether it be total avoidance or using an alternate means of damaging them. Later on, when you have a weapon, they won't be quite as menacing, but the initial encounters should definitely impart fear into the player.<br />
<br />
The Lurker waits underground in a certain spot and emerges if the player gets too close, bursting out of a hole in the ground, blowing debris everywhere. Here is my<b> </b>temp MSPaint art that I used as a placeholder for the enemy sprites so I could start working on the programming immediately:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbfOwJPd1Miy0ix_LnJatc0feFGULWRbV_IWmE_fDfMQqHfgEZhUyeHU6p2K7A7IDIAtzFBVhwBAiFjlRZhtMdeOkIGqe3gL-gDj9rbs5xCxpBX1wuVyz5oBNIFahG4ZRJ2JATQaOmPpc/s1600/lurker.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbfOwJPd1Miy0ix_LnJatc0feFGULWRbV_IWmE_fDfMQqHfgEZhUyeHU6p2K7A7IDIAtzFBVhwBAiFjlRZhtMdeOkIGqe3gL-gDj9rbs5xCxpBX1wuVyz5oBNIFahG4ZRJ2JATQaOmPpc/s400/lurker.png" width="400" /></a></div>
<br />
<div style="text-align: center;">
<i>This is why I'm working with an artist. Body/front/side/back views.</i></div>
<br />
I took a series of videos as I developed the Lurker, so you can see how it's evolved. At the end, I'll share the source code so you can see what the latest programming model against my engine looks like!<br />
<br />
<b>Part 1: The Lurker Emerges</b><br />
This video shows the lurker enemy popping out and swaying in a sinusoidal motion. It doesn't do anything interactive yet.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/o64gaQrqws0?feature=player_embedded' frameborder='0'></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>Part 2: Moving around, basic attack</b></div>
<div class="separator" style="clear: both; text-align: left;">
The lurker moves around to avoid the player, and randomly attacks him if he gets close. Then it gets stuck in the ground, and that's it.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/Zpng8xwHSp0?feature=player_embedded' frameborder='0'></iframe></div>
<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>Part 3: Real art, attacking, taking damage</b></div>
<div class="separator" style="clear: both; text-align: left;">
At this point, Allison, the artist, started working on the graphics. The initial design was a cool and creepy monster with a sideways mouth, with plans to animate it chomping the player. You can see the down-facing graphic in this video. Also, I made it so you can hit the head with weapons, and a very basic 'death' animation for the enemy.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/8gHXc1nkw78?feature=player_embedded' frameborder='0'></iframe></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: left;">
<b>Part 4: Better art, cool hit colors, refined movement. Better death animation.</b></div>
<div style="text-align: left;">
I make various (subtle) changes to the movement behavior of the enemy. Allisonchanged the head design of the monster to a more traditional shape, drew the other angles of the head, and animated the arms on the body segments. So now it's like a creepy dragon caterpillar. I added a more satisfying death explosion animation.</div>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/YlerJOdIN1I?feature=player_embedded' frameborder='0'></iframe></div>
<div style="text-align: left;">
<br /></div>
<br />
<br />
<b>Part 5: Bigger, badder, more explosive</b><br />
We increased the size of monster. A way better death animation with a bunch of explosions for the head, and a prettier hue shift during hits.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i1.ytimg.com/vi/_A61W2g0UWk/0.jpg" height="266" width="320"><param name="movie" value="http://www.youtube.com/v/_A61W2g0UWk?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/_A61W2g0UWk?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>Part 6: Snapping animations, cave shards. Job's done!</b></div>
<div class="separator" style="clear: both; text-align: left;">
I put the monster in its natural habitat, the cave. Allison added animation frames for the head so I can control its mouth--when it pulls back, it opens its mouth, and clamps shut as it attacks. Also, it opens its mouth in pain when I hit it. Allison also made better looking shards that explode out of the ground when the lurker emerges, and I added a rumbling sound (and a <i>temporary </i>hit sound) for the emerging stage. Check out the final product!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/iUbC7vxtTwY?feature=player_embedded' frameborder='0'></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>Source Code</b></div>
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: left;">
Disclaimer: I don't typically comment code except for explanations of 'why' (not 'how'--see <a href="http://www.codinghorror.com/blog/2006/12/code-tells-you-how-comments-tell-you-why.html">this article</a>) but I've marked this example up extensively for clarity. I also don't typically have classes that are anywhere near this large; my average class size is quite small, generally following the <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">Single Responsibility Principle</a>. I would probably consider breaking each enemy state into its own class. But, for the purposes of this example, I'm keeping this all in one class (for now).</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Anyway, the full source code can be found on this pastebin, <a href="http://pastebin.com/j3pjh3fA">right here</a>.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
That's all for now. Next I'm going to be fleshing out a bit more of the first cave area.</div>
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
<br />
<br />Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-33603501380103393132013-08-26T19:10:00.003-05:002013-08-26T19:10:50.519-05:00A Few Quick Development VideosI don't really have time to write a blog post, but here are a few development videos!<br />
<br />
Major Area introduction:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/9bVtxbE9Fps?feature=player_embedded' frameborder='0'></iframe></div>
<br />
Experimental enemy 'Lurker' dev video part 1:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/o64gaQrqws0?feature=player_embedded' frameborder='0'></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
And part 2:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/Zpng8xwHSp0?feature=player_embedded' frameborder='0'></iframe></div>
<br />
<br />Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-6733345103578958342013-08-16T20:53:00.002-05:002013-08-16T20:53:18.213-05:00Frame InterpolationDoing things a bit out of order this week: a video first! Keep in mind, this is a tech video about framerates:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/x36EYpUv1HI?feature=player_embedded' frameborder='0'></iframe></div>
<br />
<div>
<br /></div>
<div>
The first part of the video shows the game running at a rate of 20 <i>physical frames per second. </i>That is, the game updates its world model 20 times per second. Although the <i>real </i>rate will probably be 60 updates per second (as is common), the very small limit of 20 serves to illustrate the new feature better.</div>
<div>
<br /></div>
<div>
In this first part of the video, the game loop is running rather naively. Although the game only pushing out 20 physical frames per second, it's actually <i>rendering </i>hundreds of frames per second (on my 5 year old desktop, it's something like 750-850 FPS for the demo scene). But the game is still choppy, because it's still only updating the world model 20 times per second! With 750 <i>rendered </i>frames per second, it's actually rendering the same frame over and over about 37 times before the next physical update. What a waste!</div>
<div>
<br /></div>
<div>
The second part of the video is much smoother. You might think that I pumped up the physical frames per second to a much more reasonable number, like 60 or 200 (or maybe not--I think YouTube caps the framerate at something fairly low). But I didn't--the game is actually still running at 20 frames a second. Except now, I've introduced <i>frame interpolation.</i><br />
<i><br /></i>
Frame interpolation is exactly what it sounds like--in between any two frames (namely, the last update and the update before that one), I am able to calculate an interpolated position. For example, let's say a monster was at position (30, 40) at frame #53, and at position (40, 50) at frame #54. The sequence of events is as follows:<br />
<br />
1. The game <i>update </i>loop begins frame #54 (that is, the physical world updates--this has nothing to do with rendering!)<br />
2. All entities (actually, just entities that need to be updated--more on this later) have their transformation <i>stamped/saved</i>. This occurs before anything else, so the stamped values represent the position, rotation, scale, etc. of the entity as it was at the end of frame #53.<br />
3. The update loop runs as normal for frame #54. Entities might move around via controllers, scripts, collisions, or whatever.<br />
4. At this point, the monster has a <i>stamped </i>position of (30, 40) and a <i>current </i>position of (40, 50).<br />
<br />
Now that the update is complete, the rendering process begins. Let's say we're running at 20 physical frames per second--that's a whopping 50 milliseconds before the next update must occur, and we'll use the time to draw as many frames as possible. Let's say that rendering a frame takes 5 milliseconds.<br />
<br />
1. The game loop needs to accumulate 50 ms before the next <i>physical </i>update. We set the counter to 0.<br />
2. The interpolation value is calculated as 0/50, or 0<br />
3. The game renders with an interpolation value of 0, which means the monster is drawn at (30, 40).<br />
4. The counter is incremented to 5, so the interpolation value is now 5/50, or 0.1<br />
5. The game renders with an interpolation value of 0.1, which means the monster is drawn at (31, 41).<br />
6. This process continues until the interpolation value exceeds 1, at which point the monster will be drawn near (40, 50) and the next update will occur.<br />
<br />
This exact process is what you're seeing in the second part of the video. Of course, it's still a little messed up--you can see a noticeable lag in when the sword swings and the enemies are hit. No matter how smooth the rendering is, a game updated at 20 frames per second is going to play weird and have lag. <br />
<br />
Other than the points below, that's all for this week. I've also implemented a shield, but I'd rather wait until I have real graphics instead of the hideous temp art before showing off that one. Until next week!<br />
<br />
<i>Some points of interest / objections:</i><br />
<br />
<b>Why not just run at a variable timestep, updating as often as possible?</b><br />
<b><br /></b>
A lot of games do this. Sometimes it's a good solution, sometimes it isn't; I've read both sides of the argument. In the end, I've chosen for a fixed timestep because it yields repeatable and reliable physics results. Variable timesteps can lead to quirky behavior, such as giving those with a lower (or higher) framerate an 'advantage' in certain situations.<br />
<br />
<b>If the interpolation is linear and the object is moving non-linearly (e.g. sinusoidal or accelerated movement), won't that look weird?</b><br />
<b><br /></b>
No, not really. It's almost totally unnoticeable at 60 FPS.<br />
<br />
<b>So why bother at all?</b><br />
<b><br /></b>
On some machines, I was getting a very noticeable stutter when the timestep was capped at 60 FPS. The very popular <a href="http://gafferongames.com/game-physics/fix-your-timestep/">"Fix Your Timestep"</a> article illustrates why this happens (near the end). This stutter was a result of 'temporal aliasing.'<br />
<br />
<br />
<br />
<br />
<br />
<br /></div>
<div>
<div>
<br /></div>
</div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-76162530572372243182013-08-08T22:38:00.002-05:002013-08-08T22:38:47.562-05:00Dash, Kick, StaminaI'm a bit busy and don't have time for a proper blog post, but I still had some time to do some fun things recently. So, I'll just leave this video here, which shows a kicking (the lights), dashing, and a stamina system.<br />
<br />
Until next time!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<object width="320" height="266" class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i1.ytimg.com/vi/Vy9_GA7LkE4/0.jpg"><param name="movie" value="http://www.youtube.com/v/Vy9_GA7LkE4?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/Vy9_GA7LkE4?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<br />Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-16624692413118300032013-08-01T22:53:00.000-05:002013-08-01T22:57:04.692-05:00Gloomstone Cave: Texture Splatting and Sets, Music FadesThe best way to make an engine is to make a game with it. That's why pretty much all of my updates include some sort of practical 'demo room' scenario. Building out engine infrastructure in a vacuum is going to leave you with a worthless engine, so each update includes some sort of practical and realistic gameplay situation to help me discover gaps in the engine features.<br />
<br />
Ever since adding <a href="http://superobelisk.blogspot.com/2013/06/slabs-and-ladders.html">layer-over-layer functionality</a> and minor <a href="http://superobelisk.blogspot.com/2013/07/combining-multiple-behaviors.html">changes to the behavior structure</a>, I knew I was just about ready to start building real levels. A delay in asset creation due to Comic-Con meant I had about a week to do something else, so that's where the <a href="http://superobelisk.blogspot.com/2013/07/distortion-effects.html">distortion effects update</a> came into play.<br />
<br />
So, armed with some fresh cave tiles, I started making a game by designing one of the first accessible areas of the game, Gloomstone Cave. Two missing engine features quickly became apparent after I made a few interconnected rooms:<br />
<br />
<b>1. Randomized texture sets</b><br />
<b><br /></b>
Check out this level editor screenshot from a (fairly empty) cave room:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt6VlfdOj4E-826jQvxqvif4E6HQ24wz6uW98V0hoNwADG4SHALADkDuNA6R_asoioLuV-W0QDUXGWb3S7YPA_VCwqd4LAY36XzNvIucVNl_bR92QnhxsZzp-l4_FIaSDF3Jrkt8jrNsI/s1600/ss121.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="380" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt6VlfdOj4E-826jQvxqvif4E6HQ24wz6uW98V0hoNwADG4SHALADkDuNA6R_asoioLuV-W0QDUXGWb3S7YPA_VCwqd4LAY36XzNvIucVNl_bR92QnhxsZzp-l4_FIaSDF3Jrkt8jrNsI/s640/ss121.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>Design time...</i></div>
<br />
Now check out that very same spot, in-game:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf7hRcjGbHQkmiwOwsFhiDqBsQv1pHFZL_4pdIIQtiSBAdpjXB3szVJf2R0Xci_HmnHkIIJ1pY9LkbSI5spDL1C_ffjE_RrJxAUZ1ZSFTBvdupJiSZkWp_qyyJjIrSLwDX8EJNyndjRGw/s1600/ss122.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="417" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf7hRcjGbHQkmiwOwsFhiDqBsQv1pHFZL_4pdIIQtiSBAdpjXB3szVJf2R0Xci_HmnHkIIJ1pY9LkbSI5spDL1C_ffjE_RrJxAUZ1ZSFTBvdupJiSZkWp_qyyJjIrSLwDX8EJNyndjRGw/s640/ss122.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>...and run time.</i></div>
<br />
Notice anything? It's subtle, but there are actually two separate floor tiles--one is 'plain' and one has a slight pebble decoration to it. But if you look at the level editor, you'll see that it's all just one tile.<br />
<br />
I'm not claiming this is some kind of technical wonder. It's not--it actually only took me a few minutes to add <i>random texture set </i>metadata to the texture editor, seen below.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd9Bd4Cz6C8Z69SukUY23tz-S_dlhEQHVMwdwhLHTYwFnyvaoc-q2dg1wN4Q_qH61DCRjMCPOzbvMSl7aWE_gv25yAgQI-taEnIBkSdwiVzmYfUQjaXYSmlD5prijWdOwhO4v5Wiqj1Dg/s1600/ss123.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd9Bd4Cz6C8Z69SukUY23tz-S_dlhEQHVMwdwhLHTYwFnyvaoc-q2dg1wN4Q_qH61DCRjMCPOzbvMSl7aWE_gv25yAgQI-taEnIBkSdwiVzmYfUQjaXYSmlD5prijWdOwhO4v5Wiqj1Dg/s320/ss123.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<i>A screenshot of the texture editor for a single texture, cave_floor</i></div>
<div class="separator" style="clear: both; text-align: center;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: left;">
So, if two textures are tagged with the same 'random set' property, it means at run-time, when the level loads, a random texture from that set will be selected. The reason for this? There's absolutely no point in wasting design time picking out from a set of tiles when the goal is to just randomize them anyway. The minute I caught myself alternating between the pebbled and regular floor tile, I realized that adding this little feature would save me hours of time later.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>2. Texture Splatting</b></div>
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: left;">
Another thing I noticed when designing the cave floor is that it was boring with the same tile (well, two similar tiles) everywhere. I had a temporary 'path' tile to use, which looks like this:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://i.imgur.com/m9m5oLT.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="197" src="http://i.imgur.com/m9m5oLT.png" width="200" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>A temporary path tile, straight from Google Image Search</i></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Problem is, this looks pretty mixed in with the cave floor:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5Vac1Bcnv6zx7T4-Z0q1W68bAE2VtrzIPP77tW9xj0fnbRlpBYugMuZQ9n6fhmlhyIA99_AOzxH91Lpj8k_AfLmEUQ5M55IUYqscuBOSmWTxNkICfHx6dxLk_LPMaMZMFVbVzd_vtYJE/s1600/ss124.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5Vac1Bcnv6zx7T4-Z0q1W68bAE2VtrzIPP77tW9xj0fnbRlpBYugMuZQ9n6fhmlhyIA99_AOzxH91Lpj8k_AfLmEUQ5M55IUYqscuBOSmWTxNkICfHx6dxLk_LPMaMZMFVbVzd_vtYJE/s320/ss124.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>Bad</i></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The naive solution to this issue is to make nice 'edge' versions of the tile so that it blends in. I might need one for each side--I can't just rotate them, since that would throw off the tiling of the rest of the image. Oh, and wait, I need 4 more for the corners. Oh, that's just the convex corners, I'll need 4 more for concave corners. Now we're talking about 12 tiles.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
That's doable, but a pain in the ass to maintain. If I want another path--or grass growing on the cave floor, or water--do I have to create 12 more tiles for each one? When I make a change to one of those tiles, do I have to update all 12? Yes. That sucks.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
What if I could just dynamically apply an alpha map to the <i>single </i>tile, and do it at run-time instead of design time? That's sort of the idea behind <a href="http://en.wikipedia.org/wiki/Texture_splatting">Texture Splatting</a>. So, I added that to the engine. Here's how it works.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b><i>1. Create a custom splat map</i></b></div>
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: left;">
I still have to create those 12 'edge tiles', but I create it as a re-usable alpha map. Here's what it looks like currently. I will probably add a lot more of these, including some more rugged ones. I call it my 'splat map.'</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoDwz77jP4dWB1Bfex2LJjfzpTwQ0XtR7vYu2Gp2IWerCrz1juKReXE0B4Bvbxb0y1ZAon_L04fF41KCuGfVMeGHRomKn3ShRj7FDjs18Wwq6RD1wH5LWgs4Uz3v3oQOeOSeYpN9KCwRA/s1600/splats.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoDwz77jP4dWB1Bfex2LJjfzpTwQ0XtR7vYu2Gp2IWerCrz1juKReXE0B4Bvbxb0y1ZAon_L04fF41KCuGfVMeGHRomKn3ShRj7FDjs18Wwq6RD1wH5LWgs4Uz3v3oQOeOSeYpN9KCwRA/s1600/splats.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>That's actually 12 square textures, even though it kind of looks like 6.</i></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b><i>2. Pass in the splat map texture along with texture coordinates to the fragment shader.</i></b></div>
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: left;">
A few of my shaders now have a segment of code like this:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both;">
if (fragSplatUV.x >= 0)</div>
<div class="separator" style="clear: both;">
{</div>
<div class="separator" style="clear: both;">
result.a *= texture(splatTexture, fragSplatUV).r;</div>
<div class="separator" style="clear: both;">
}</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
So, entities (which includes tiles) have optional 'splat coordinates' that get passed in. I use -1 for the x value to indicate 'no splat', which saves me from having to do an extra texture lookup (which is probably true for about 95% of the entities). Note that I only use the red component of the splat map; maybe in the future I could use the same texture for other metadata, and only store splats in the red channel.<br />
<br />
<b><i>3. Apply splats in the level editor</i></b><br />
<b><br /></b>
Pressing 'b' in the level editor launches the splat picker:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNujSO89NMCwL2OMPutx8aRKr46SLLXRdUVXWzwHnkW7fuk3Q9O63DDslpCso8jDgJSEq1LcU9kICG8jcghj06N5DQspwhOxJa1yYUSky81MUkqtMVckJH20c-SZJFBw01TurPqxFY44A/s1600/ss125.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNujSO89NMCwL2OMPutx8aRKr46SLLXRdUVXWzwHnkW7fuk3Q9O63DDslpCso8jDgJSEq1LcU9kICG8jcghj06N5DQspwhOxJa1yYUSky81MUkqtMVckJH20c-SZJFBw01TurPqxFY44A/s320/ss125.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>The splat selector</i></div>
<div class="separator" style="clear: both; text-align: center;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: left;">
<b><i>4. Make things a bit prettier</i></b></div>
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: left;">
Here's a result of me adding a bunch of splats to that ugly segment:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9WUn8ftWkERSm7ZN-G_d2hhPai2o72sqC2OyTy8B9FmWwpUVQsQ5zCma4hOBteKpAGd2icAts57Psuihfon6aJFE5cgVkrRsvOGXZiiLZbX91Qa_C5H0fQ-EpqHzhwd_cJpCaIF_Z674/s1600/ss126.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9WUn8ftWkERSm7ZN-G_d2hhPai2o72sqC2OyTy8B9FmWwpUVQsQ5zCma4hOBteKpAGd2icAts57Psuihfon6aJFE5cgVkrRsvOGXZiiLZbX91Qa_C5H0fQ-EpqHzhwd_cJpCaIF_Z674/s320/ss126.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>Looks better than before</i></div>
<div class="separator" style="clear: both; text-align: center;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: left;">
And here it is with an old grass texture:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTQmo6PdqFuzbC2HJdVx1_Hp7UMu7Od5o1MGWRNg1xC5jm2TmO3J6eiJ8husfUl025dYgtWjhvHLUgv0s5IDPssb5a6oB5LQpUUKh6rwkYc6Hh81czAekmIz8sWx3y3HkspXheP7KBYJU/s1600/ss127.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTQmo6PdqFuzbC2HJdVx1_Hp7UMu7Od5o1MGWRNg1xC5jm2TmO3J6eiJ8husfUl025dYgtWjhvHLUgv0s5IDPssb5a6oB5LQpUUKh6rwkYc6Hh81czAekmIz8sWx3y3HkspXheP7KBYJU/s320/ss127.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>It's grassy now</i></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
So, even with minimal extra textures, it looks much better! Of course, it still isn't perfect--it still looks slightly artificial instead of organic. But that's just a matter of updating the splat maps to have more rugged and randomized edges instead of the straight lines and perfect curves that are there now.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
That's all for the texture updates.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<b>3. Music Fading</b><br />
<b><br /></b>
Just a quick little feature, I made it music transitions smoothly from one area to another. Here is a little video that shows that, as well as demonstrating a basic walk-around through various empty sections (I'll be making them more interesting really soon). Also, check out the cool light shaft effect at the cave entrance!<br />
<br />
Note that I'm using palace textures outside since I don't have the proper outdoor cave textures yet.<br />
<br />
Enjoy the video and see you time!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/BwCiDcsUuRw?feature=player_embedded' frameborder='0'></iframe></div>
<br />
<br />
<br />
<br />
<br />
<br />Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-54664440225964894172013-07-22T21:08:00.000-05:002013-07-22T21:25:04.985-05:00Distortion EffectsHi, it's time for a super rad tech update! Last week, I mentioned something about music...well, I needed some art to really show it off correctly (Art? For music?) so I did something else this week instead: <b>distortion effects!</b><br />
<div>
<br /></div>
<div>
This update will include a fairly technical overview of my graphics pipeline. If you'd rather just see the cool special effects, you can skip straight to the bottom and enjoy the video.</div>
<div>
<br /></div>
<div>
A popular graphics technique is to warp sections of the screen. This can be used for all sorts of effects, such </div>
<div>
as shock waves, fish-eye lenses, translucent surfaces, heat hazes, etc. Here are some examples, taken from the first few pages of a Google image search for '2d distortion shader':<br />
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://img682.imageshack.us/img682/5864/griddistorted.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://img682.imageshack.us/img682/5864/griddistorted.png" width="320" /></a></div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.paradeofrain.com/images/warped.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="http://www.paradeofrain.com/images/warped.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.oxmonline.com/files/u10/dust_screen_1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="223" src="http://www.oxmonline.com/files/u10/dust_screen_1.jpg" width="400" /></a></div>
<br /></div>
<div>
Step by step, I'm going to go over how I implemented the infrastructure in the engine for Super Obelisk. For clarity, I'm just going to go over the entire graphics pipeline, including the lighting and slabs (layering) components. One nifty little trick--and this is very useful during development--is the ability to save the contents of the current OpenGL frame buffer (i.e., render surface) to a file, so we can see what's being drawn behind the scenes before the final image is presented to the user.</div>
<div>
<br /></div>
<div>
The following image is our <i>final result</i> for this example.</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQRWqkUNA1V-4gD8QwdPlfQdUEH112LSTLf2AaLGafZP5ovWj_B0MEjB9nnC6_hKugywVLBHAwJhExEB2qHJSphFe2lT9oUQJUyZTa4stx_km394QmNI7_HiOfhcfl3CuYk-7uGl4V1Cc/s1600/ss109.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQRWqkUNA1V-4gD8QwdPlfQdUEH112LSTLf2AaLGafZP5ovWj_B0MEjB9nnC6_hKugywVLBHAwJhExEB2qHJSphFe2lT9oUQJUyZTa4stx_km394QmNI7_HiOfhcfl3CuYk-7uGl4V1Cc/s400/ss109.png" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br /></div>
<div>
Note the following features:</div>
<div>
<br /></div>
<div>
1. The scene has multiple slabs. The player is rendered on the bottoms slab. Some blobs are on the top slab.</div>
<div>
2. Lights from the bottom slabs don't shine to the top slab. Lights from the top slab, however, shine to the bottom slab.</div>
<div>
3. A distortion bubble on the lower slab is obscured by the upper slab (overpass). Also, the bubble does not show the contents of the upper slab.</div>
<div>
4. The distortion bubble on the upper slab, however, contains the entire scene, <i>including the other bubble on the lower slab</i><b style="font-style: italic;">! </b></div>
<div>
5. Two distortions on the right side of the screen represent a pure left shift and a pure right shift. Where the sprites overlap, there is no distortion, since they cancel each other out. This is kind of hard to see without zooming way in and looking carefully at the floor tiles.</div>
<div>
<br />
And now, how we got to this scene. The engine gathers up all render data and sorts it into separate rendering layers. In this example, there are two slabs being rendered. I've removed the HUD for simplicity. Here's what happens:<br />
<br />
<b>1. Lights on </b><i style="font-weight: bold;">both slabs</i> <b>are rendered.</b><br />
<b><br /></b>Lights are on a special layer type and are drawn with a very simple shader which converts world position to screen position via a transformation matrix. The results are stored in the <i>lights buffer</i>. Note that the 'clear color' is the ambient color of the section.<br />
<br />
Because we want lights from the upper slab to shine down onto the lower one, we render <i>all </i>lights that are 'on or above' the current slab.<br />
<br />
Here is what the lights buffer looks like after this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9Qi8rFZTa_XtyplOCaFn1V1jb8-c723bhqi4p-yaagnEg2WBZM7Y6kA07Tm09RFR_2NV_OSKTAYc25V9Rp5RdWykN2OzgDWmuhDLI694sSXeBj7wSevFklqFw3ctu06gFPPhfsX63X5I/s1600/output-1.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9Qi8rFZTa_XtyplOCaFn1V1jb8-c723bhqi4p-yaagnEg2WBZM7Y6kA07Tm09RFR_2NV_OSKTAYc25V9Rp5RdWykN2OzgDWmuhDLI694sSXeBj7wSevFklqFw3ctu06gFPPhfsX63X5I/s400/output-1.bmp" width="400" /></a></div>
<br />
<br />
<b>2. Distortion sprites on the lower slab are rendered.</b><br />
<b><br /></b>
Next, we'll render the distortion sprites to the <i>distortion buffer</i>. The shader for these is the same as the lights buffer--a very simple world-to-screen transformation. I've actually slightly modified the output here for demonstration purposes only--since an alpha value of '0' is typical for pixels (keep reading to find out why), you wouldn't even be able to see most of the image if I didn't set set the alpha to '1' for this image. The result of this rendering:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXXSzqT0RaHw99trYg2EYdWMvmtJ0izX_k2OHm5yfLnSk23KMVvbHpV6cBDqIuDIQkFtc3U_F5Yv3_eQLKxG4SRSOriygI9mizXurGk4ZZkHry9cYQzoOVPF9DMmJCZbTklli1j2oUTBI/s1600/output-2good.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXXSzqT0RaHw99trYg2EYdWMvmtJ0izX_k2OHm5yfLnSk23KMVvbHpV6cBDqIuDIQkFtc3U_F5Yv3_eQLKxG4SRSOriygI9mizXurGk4ZZkHry9cYQzoOVPF9DMmJCZbTklli1j2oUTBI/s400/output-2good.bmp" width="400" /></a></div>
<br />
<br />
<br />
<b>3. The scene on the lower slab is rendered and combined with the lights.</b><br />
<b><br /></b>
At this stage, the bulk of the rendering occurs. All remaining entities (tiles, players, enemies, particles, etc.) are rendered onto another buffer, which we'll call <i>bufferA</i><b style="font-style: italic;">. </b>The shader program for this part of the rendering uses the <i>light buffer </i>from step 1 as a source texture. Each pixel multiplies its output with the corresponding pixel of the light texture. Although not pictured, this shader is also responsible for hue shifts like when an enemy gets hit and flashes different colors (or when a bomb is about to explode). Here's what we have so far; keep in mind there's something fishy about how the alpha channel is saved to the file, which is why the shadows look odd in some of these pictures:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRothqxvPB_-nM9WSWx_CvqrA-DGDGa6xSrDsR9PXGLLJwecmfD1KsTh5VIsXUt8KWhYBmSTrVudWwsbY6ZtGZiniFZlSpqtv3WySRt0NjLctzgyk0LlXR7zrlWmzRpVamnNtp7_fSdBc/s1600/output-3.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRothqxvPB_-nM9WSWx_CvqrA-DGDGa6xSrDsR9PXGLLJwecmfD1KsTh5VIsXUt8KWhYBmSTrVudWwsbY6ZtGZiniFZlSpqtv3WySRt0NjLctzgyk0LlXR7zrlWmzRpVamnNtp7_fSdBc/s400/output-3.bmp" width="400" /></a></div>
<br />
<br />
<b>4. Distortion is applied</b><br />
<b><br /></b>
Now, we take the output from step 3 (<i>bufferA</i>, in this case) and copy it to <i>bufferB.</i><b style="font-style: italic;"> </b>The copy will use the distortion map from step 2 to warp the picture. The default case, where eveything (RGBA) is 0, will just do a straight copy of the pixel (no distortion). So, on bufferB, a pixel at (25, 10) would be sampled directly from (25, 10) on bufferA.<br />
<br />
But if the pixel isn't pure black, we apply distortion on the X and Y axis<br />
<ul>
<li><b>Red </b>represents a distortion to the left</li>
<li><b>Green </b>represents a distortion to the right. </li>
<li><b>Blue </b>and <b>Alpha </b>represent a distortion up and down, respectively.</li>
</ul>
<div>
A popular distortion scheme is to use only the Red and Green channels of the texture for left and right distortion; Red values less than 0.5 (or 128 on a 256 value scale) represent a left shift, while Red values greater than 0.5 represent a right shift. Green controls the Y axis. Here is an image I found online that is used for that distortion algorithm:</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN_oYnw1GwIMDi2wOZlw4YOiRb2oTxnNq_ZHyZGakS5F7oAe08BDvo06cRfZdXlDtWjjoORCwh0f90sTcz4hIIDMfQuAokRaFVoojnBEiODWRnV2IiAuFy4-Dq9pLh2pTqu2qNSgSFck8/s1600/distortion.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN_oYnw1GwIMDi2wOZlw4YOiRb2oTxnNq_ZHyZGakS5F7oAe08BDvo06cRfZdXlDtWjjoORCwh0f90sTcz4hIIDMfQuAokRaFVoojnBEiODWRnV2IiAuFy4-Dq9pLh2pTqu2qNSgSFck8/s200/distortion.png" width="200" /></a></div>
<br /></div>
<div>
The problem with this scheme is that it doesn't work well with additive blend, meaning distortions can't be overlapped with any meaningful result. For example, a solid sprite with RGBA = (0.4, 0, 0, 0) would be a slight left shift. But two of those overlapped with additive blend would be RGBA = (0.8, 0, 0, 0)--which is actually a <i>right </i>shift, instead of a stronger left shift!</div>
<div>
<br /></div>
<div>
My scheme, however, correctly intensifies the shift as sprites overlap--or cancels the shift out entirely if, say, the Red and Green components line up (which is exactly what the example image is showing with the distortion boxes!)</div>
<div>
<br /></div>
<div>
Anyway, here's the output of <i>bufferB:</i></div>
<div>
<i><br /></i></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjug16F9dkgB1nddaIfVPLPZlAsBuf8SPTmzzwys-P1sY8NvXnYj8dhYLgDGH7sfKdYRy2QIlxnNYUtm_-SOOwEj4eMaIGWgd7AtBSID5plSv8gVmU0fQXDv1t93LFPXXDZbrgaFYzCcU8/s1600/output-4.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjug16F9dkgB1nddaIfVPLPZlAsBuf8SPTmzzwys-P1sY8NvXnYj8dhYLgDGH7sfKdYRy2QIlxnNYUtm_-SOOwEj4eMaIGWgd7AtBSID5plSv8gVmU0fQXDv1t93LFPXXDZbrgaFYzCcU8/s400/output-4.bmp" width="400" /></a></div>
<br />
<br />
<b>5. Render the lights on the next slab.</b></div>
<div>
<i><br /></i></div>
<div>
We clear the <i>light buffer </i>from step 1 and render the lights on the upper slab only. Lights from the lower slab do not affect the items we're about to draw!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoe4mMAfPaNQN03C9eQzGur1Z8VduRUYqkKFbwqpcRKkDSTaWtBqj8lyma3fYZoTe2RkANgyz_vDomP7-2fo9PddHJycUnJgsLs61nOwnzY7vrpE5xZyGHBdupg2eOxs5v_80T7IxhS_M/s1600/output-5.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoe4mMAfPaNQN03C9eQzGur1Z8VduRUYqkKFbwqpcRKkDSTaWtBqj8lyma3fYZoTe2RkANgyz_vDomP7-2fo9PddHJycUnJgsLs61nOwnzY7vrpE5xZyGHBdupg2eOxs5v_80T7IxhS_M/s400/output-5.bmp" width="400" /></a></div>
<br />
<br />
<b>6. Render the distortion sprites on the next slab.</b><br />
<b><br /></b>
We clear the distortion buffer and do the same as in step 2. Nothing fancy here. There's only one distortion sprite on the upper slab:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqjoPVwC9pAhastepwXXughuf0l3F3DdhW1-n71iCaQmDlLAAzEa6noSEgpbV6sQFpQQCZJ2eX_ldB9Eh74EIYUMCYtkQ_IqYwlq6HjQlR1sI4DaDftZv5ZDy0gx976RR-3UrCNVpHwEg/s1600/output-6good.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqjoPVwC9pAhastepwXXughuf0l3F3DdhW1-n71iCaQmDlLAAzEa6noSEgpbV6sQFpQQCZJ2eX_ldB9Eh74EIYUMCYtkQ_IqYwlq6HjQlR1sI4DaDftZv5ZDy0gx976RR-3UrCNVpHwEg/s400/output-6good.bmp" width="400" /></a></div>
<br />
<br />
<b>7. The normal scene of slab 2 is rendered onto bufferB, combined with lights from step 5.</b><br />
<b><br /></b>
Remember, <i>bufferB </i>represents the <i>entire </i>output of the first 4 steps. We're using the "painter's algorithm" here--we're going to draw right on top of all the other stuff we just drew. Note that we do <i>not </i>clear this buffer before this step, which is crucial. Here's what we have now:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-xSzNmM2Yl5JbxG8TbmzZblz1vUBCGjBrcSqxHhFSVY7YQw0Ayo_Q7G55ACaZkICdWepedJkWwQgGFhO4YLiIk0GWS33YQqALH1X1G3MnkvaxerrWIWViAe7SmcZens1mJ76H3fUNfpw/s1600/output-7.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-xSzNmM2Yl5JbxG8TbmzZblz1vUBCGjBrcSqxHhFSVY7YQw0Ayo_Q7G55ACaZkICdWepedJkWwQgGFhO4YLiIk0GWS33YQqALH1X1G3MnkvaxerrWIWViAe7SmcZens1mJ76H3fUNfpw/s400/output-7.bmp" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<br />
<b>8. Distortion from step 6 is applied.</b><br />
<br />
Similar to step 4, we're going to apply distortion. Except this time, we're <i>sampling </i>from bufferB and <i>writing </i>to bufferA. For every slab we render, these two buffers are alternated--we need both of them, but once we're done copying from one to another, we don't need the first one any more, so we reuse it.<br />
<br />
Note that the distortion sprites on slab 2 may sample distortion output from slab 1! So, sometimes you can see a ball reflected on another ball.<br />
<br />
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQRWqkUNA1V-4gD8QwdPlfQdUEH112LSTLf2AaLGafZP5ovWj_B0MEjB9nnC6_hKugywVLBHAwJhExEB2qHJSphFe2lT9oUQJUyZTa4stx_km394QmNI7_HiOfhcfl3CuYk-7uGl4V1Cc/s1600/ss109.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="496" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQRWqkUNA1V-4gD8QwdPlfQdUEH112LSTLf2AaLGafZP5ovWj_B0MEjB9nnC6_hKugywVLBHAwJhExEB2qHJSphFe2lT9oUQJUyZTa4stx_km394QmNI7_HiOfhcfl3CuYk-7uGl4V1Cc/s640/ss109.png" width="640" /></a></div>
</div>
<br />
...and we're done!<br />
<br />
So, what can this be used for? A little reflective orb here and there looks cool, but has limited usage. I put together a video of me walking through a few rooms showing different ways this effect can be used--and I've only had it for a couple days, so I haven't gotten around to discovering what other things I can do with it yet. Check out the video! Also, if you like seeing stuff like this in development--including horrible screenshots of when things go wrong--I usually put those on twitter, at <a href="https://twitter.com/ericswheeler">https://twitter.com/ericswheeler</a> .<br />
<br />
Video:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/IilEyMzqCrU?feature=player_embedded' frameborder='0'></iframe></div>
<br />
Thanks for reading/watching and see you soon!<br />
<br />
<br />
<br /></div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com3tag:blogger.com,1999:blog-648173414442845757.post-31979390842722447832013-07-15T20:04:00.001-05:002013-07-15T20:04:30.340-05:00Combining Multiple BehaviorsIn last week's entry, I made a note at the end that there was a limitation in the way I had designed how <b>Behaviors </b>are attached to <b>Entities--</b>namely, that I was limited to one behavior per entity. This post is about how I solved the issue.<br />
<div>
<br /></div>
<div>
<i>Technically</i>, that's fine, since Behaviors are just references to code, and can be as complicated as I want them to be. But it doesn't necessarily yield good design with respect to reusable components. Let's take an example.<br />
<br />
Let's say I have an entity with the lit torch graphic and I attach the <b>ThrowableItem </b>behavior to it:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSoGW3mlxb8H3LemFC3q8VMZZNFusUt7xx0utvwWMc3tgU4xabBEi8ygywJeUOUBWXIWLD4Dqwfv8Bhw5Z82p_yHugFQm9U9U_20_SlkoafLiQjEjugoL8qxEj0QzOUbgNqpjIKQCi2aw/s1600/pickup.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="161" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSoGW3mlxb8H3LemFC3q8VMZZNFusUt7xx0utvwWMc3tgU4xabBEi8ygywJeUOUBWXIWLD4Dqwfv8Bhw5Z82p_yHugFQm9U9U_20_SlkoafLiQjEjugoL8qxEj0QzOUbgNqpjIKQCi2aw/s200/pickup.gif" width="200" /></a></div>
<br />
<br />
And here's another entity with the <b>PointLight </b>behavior attached (the <b>PointLight </b>behavior attaches a child entity configured as a light source, and has a few editable parameters such as size and color).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihg1feXTbv9S_8Gf3MMB2kxWzwzPtGuNkgFovT3QrfuDSiXuPyFU6GkKi1mbPYEtspdq7bZO6p9mG5BeWFo17Qc49vm9wgzVJiB64tqcendFS_mgoMa_GZTKXnmNI6a_lyp_jJliGDcS0/s1600/light.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihg1feXTbv9S_8Gf3MMB2kxWzwzPtGuNkgFovT3QrfuDSiXuPyFU6GkKi1mbPYEtspdq7bZO6p9mG5BeWFo17Qc49vm9wgzVJiB64tqcendFS_mgoMa_GZTKXnmNI6a_lyp_jJliGDcS0/s200/light.gif" width="200" /></a></div>
<br />
<br />
But what if I want to pick up the torch with the light on it? One solution would be to introduce an editor property to the <b>ThrowableItem </b>behavior, something like <i>IsLightSource. </i>Then, when the behavior is initialized, I could add a light entity as a child item. Unfortunately, that's a bad design.<br />
<br />
Imagine I have another behavior called<b> SpawnHeartWhenDestroyed </b>which makes it so an entity drops a heart refill when its destroyed. Currently, when I throw an item and it hits the ground, it's destroyed. Would I <i>really </i>want to add a property to <b>ThrowableItem</b>, called <i>SpawnsHeart </i>that duplicated this behavior? What if I wanted a certain instance of an enemy to spawn a heart?<br />
<br />
What's the point in having these nice componentized behaviors if I can't reuse them at will?<br />
<br />
To solve this problem, I simple made<b> </b>it so an Entity can have multiple attached behaviors. Do you want your blob to also be a light source, spawn a heart when destroyed, and shake the screen every 6 seconds? No? Well, if you could if you wanted to. As a much more practical example, here's a torch that has both <b>ThrowableItem </b><i>and </i><b>PointLight</b> attached, which was the original inspiration for this architecture change. Check out the video!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/Zpjv7wMXylo?feature=player_embedded' frameborder='0'></iframe></div>
<br />
<br />
Here is what the level editor looks like with this new feature. Launching the 'entity properties editor' of a single entity now shows a tabbed collection of behaviors--each with their own properties--instead of just one. Add and remove properties at will!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh89Y2v481QDqkaZFyAUkq4RGp3LJB6HoFoYJuvluqG8PjbdMMcaZh0lCbCe-i5OfGf6bp7jWTHAr7S_MOWIMRd6b8A71iDy7GlI6C5ituEA8P8OBcOcyhw-hbFN3hdIq4igrDeWNK6P_s/s1600/ss101.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="247" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh89Y2v481QDqkaZFyAUkq4RGp3LJB6HoFoYJuvluqG8PjbdMMcaZh0lCbCe-i5OfGf6bp7jWTHAr7S_MOWIMRd6b8A71iDy7GlI6C5ituEA8P8OBcOcyhw-hbFN3hdIq4igrDeWNK6P_s/s400/ss101.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>The entity properties editor--note the multiple behavior tabs</i></div>
<br />
<br />
But remember, in the end, these behaviors are all <i>acting </i>on the same entity--that is, they could easily conflict if they both modify the same entity in incompatible ways. For example, you can't just make a <b>Blob</b> a <b>ThrowableItem. </b>You can <i>try, </i>but you're sure to get some weird behavior, since both of those things interact with the player in a mutually exclusive way. Is this a limitation of the engine? No, definitely not--the types of behaviors you'd expect from something that's both an enemy <i>and </i>throwable are just too complex to be automatically applied--it takes actual human programming to decide what it means to be an enemy and throwable. For example, does the enemy still damage the player when colliding with the player model? Does the graphic change? The engine can definitely allow you to define these things, but you'll have to do it explicitly in code.<br />
<br />
As a bonus, here's a fun little video of a spotlight that follows the player around when he gets close.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<object width="320" height="266" class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i1.ytimg.com/vi/2oG7da_XSA0/0.jpg"><param name="movie" value="http://www.youtube.com/v/2oG7da_XSA0?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/2oG7da_XSA0?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<br />
Next up I'll be doing some things with music. Stay tuned and thanks for reading!<br />
<br /></div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com2tag:blogger.com,1999:blog-648173414442845757.post-743314015492440242013-07-07T12:36:00.002-05:002013-07-07T12:36:13.377-05:00Throwing Stuff AroundThis is going to have to be a quick post because I don't have a lot of time, but still want to keep readers updated.<br />
<br />
I added the ability to <b>pick up and throw</b> items. I've implemented a <b>Behavior </b>called 'ThrowableItem' which can be attached to entities in the editor. Here's a little preview:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibQxLeT3fR4Al7BdomA-e76aVlOHqVtQekEX6u37oOiuCg_vcVWq2ORPb6ssqYuK9sJm4J8cynMZ_jDP-RtSkhibycoZ76n0yCxfjKy552SA8BLwbgIZjVS_K72dw_SjyLoI-LCjIL_t0/s1600/ss5.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibQxLeT3fR4Al7BdomA-e76aVlOHqVtQekEX6u37oOiuCg_vcVWq2ORPb6ssqYuK9sJm4J8cynMZ_jDP-RtSkhibycoZ76n0yCxfjKy552SA8BLwbgIZjVS_K72dw_SjyLoI-LCjIL_t0/s1600/ss5.gif" /></a></div>
<br />
And here's a full video, in which you can enjoy the sound and music of Link to the Past (temporary!)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/UAcItUDTcZc?feature=player_embedded' frameborder='0'></iframe></div>
<br />
When I finished doing this, one thing I immediately realized is that I couldn't have a brazier be *both* a light source AND a throwable item, because currently the editor (and game infrastructure) allow the (optional) attachment of exactly one <b>Behavior </b>to each entity. I'd like to be able to pick up a lit brazier and throw the light around. So, today I'm going to make it so you can attach multiple behaviors to one entity. This is going to require three things: an infrastructure change in the engine, a level editor change in the GUI for the behavior editor (which will become the behavior <i>collection </i>editor), and a small refactoring in the current implementation assembly.Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-21381503037640754102013-06-30T00:47:00.002-05:002013-06-30T00:47:32.883-05:00Four FeaturesFour quick features added to the engine this week:<br />
<br />
<b>1. Layer Sort Types</b><br />
<b><br /></b>
There are now two ways to configure the rendering algorithm for a given layer. The first method, 'batch mode', is what I've been using all along. If you're familiar with graphics programming, you've probably employed this technique many times: minimizing the number of render state switches (and texture switches) can drastically improve performance. So, quads that are similar are grouped together and drawn as batches.<br />
<br />
2D games often don't use depth buffers (or if they do, it usually means a sacrifice with respect to partially transparent pixels)--instead, they use the 'painters algorithm', which just means drawing things front-to-back. But batching things together can lead to undesired results. Check it out:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu25wYpbDa1rsaXwskaniHmxa5ojl90CgLwdl15Gq-89-LIHIX2ljosN-0C27THcW9mBzPxkfDNiaZE2BtTp_LPfEKmhAPJoqTna80v8ZejPBy6EfIPifS71lJPuk1cMzS_9M5NnVGNhQ/s1040/ss92.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu25wYpbDa1rsaXwskaniHmxa5ojl90CgLwdl15Gq-89-LIHIX2ljosN-0C27THcW9mBzPxkfDNiaZE2BtTp_LPfEKmhAPJoqTna80v8ZejPBy6EfIPifS71lJPuk1cMzS_9M5NnVGNhQ/s400/ss92.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>The player is rendered incorrectly</i></div>
<div class="separator" style="clear: both; text-align: center;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: left;">
In this case, as it happens, the blobs are all from the same texture, so they're batched together as a single call. Then the player is drawn. But that looks wrong, since the blobs right below the player should be rendered <i>after </i>the player.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
In fact, what we really want to do here is sort every texture to be drawn by its <b>lowest Y-coordinate </b>(bottom) and then draw from the top down. So, the blobs 'above' the player (i.e. on the top half of the screen) are drawn, then the player, then the blobs 'below' the player.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Here's what that looks like:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho59Cax32ZdNiOUQ7KK5BjsLamPIlzt27J6Kq_6pRNUAD4xe3sF93tadl2LrEC2lPLdGDl0LaoKdWyzjDFWmT8lEvwIotfSJLAFGkBpEabB_4Va2qsKjwgzSvUky_M6WHXllYzqhCeXfs/s1040/ss91.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho59Cax32ZdNiOUQ7KK5BjsLamPIlzt27J6Kq_6pRNUAD4xe3sF93tadl2LrEC2lPLdGDl0LaoKdWyzjDFWmT8lEvwIotfSJLAFGkBpEabB_4Va2qsKjwgzSvUky_M6WHXllYzqhCeXfs/s400/ss91.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>Much better.</i></div>
<div class="separator" style="clear: both; text-align: center;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: left;">
The question is, how can optimal batching <b>and</b> this drawing algorithm be achieved? The first picture is done in 2 batches, the second picture in 3 batches. And the answer is that I don't know and I don't really care right now--the majority of the sprites in the game aren't going to need this slightly slower rendering process, just ones on the layer I've dubbed 'action layer' (where the player, enemies, and a few other things lie on). The majority of entities will still live on 'batched' layers--particles, floors, walls, weather effects, font characters, etc.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>2. Advanced Model Configuration</b></div>
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: left;">
I had some pre-defined model 'shapes' built into the engine, but that wasn't really the best design. <a href="http://superobelisk.blogspot.com/2012/12/adding-collision-to-entities.html">This older blog post</a> (namely, the video linked in it) shows how I would go about adding a new shape. But as soon as I realized I needed a special shape for the 'blob' enemy (and surely many, many more as I added more enemies), it was time to move model declarations out of the engine and into the implementation assembly. That is, every game using the engine can define their own collision shapes dynamically--and use them in the editor!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
Here is a picture that shows the blob model outline with a series of particles that stop when they 'leave' the blob:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2ft_iwGPwiZlkxBz-j2ThhlpoCY_mf0aYi9oAR6w-7V5QdxCs1atOcSfkqf6zpobgldFTO-cjWNRVF1xqoFH6Ocrh7EajasQnqKvT-gsjrCfKkF2Asq1GSiPqWAbMqXwGv3v3REqQaFk/s1040/ss89.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2ft_iwGPwiZlkxBz-j2ThhlpoCY_mf0aYi9oAR6w-7V5QdxCs1atOcSfkqf6zpobgldFTO-cjWNRVF1xqoFH6Ocrh7EajasQnqKvT-gsjrCfKkF2Asq1GSiPqWAbMqXwGv3v3REqQaFk/s400/ss89.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>The white particles stop when they reach the blob's collision model edge</i></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
This may seem minor, but I want to focus on having a really tight gameplay experience, and having complete control over collision models is necessary for that.<br />
<br />
<b>3. Screen Shake</b><br />
<b><br /></b>
Well, this one's simple enough. I added support for screen shaking (which is really just rapidly moving the camera). Here's a clip.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/fnF-zFkWZIU?feature=player_embedded' frameborder='0'></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
<i>Big blobs landing shake the screen</i></div>
<div class="separator" style="clear: both; text-align: center;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: left;">
For testing purposes I coded it so that when a blob lands it shakes the screen at a certain strength for a certain duration, but it's a one-liner in code now so I'll be able to quickly add it wherever appropriate.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>4. Font Kerning</b></div>
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: left;">
I fixed my font renderer so that it uses kerning data to properly display characters.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJTOHpZ-Q3DzGsBrKQll6oYNNx4pjLC2RBOoTEPNE1JgNb6EFv58NhAGkfEv3fHa9R6tvC2QAGSwKpThotAnfGlY5z0LThBO4ba_faEIzCdJOio_J4uOz9OdDFjCbajQ9od_gNlfytw80/s1040/ss93.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJTOHpZ-Q3DzGsBrKQll6oYNNx4pjLC2RBOoTEPNE1JgNb6EFv58NhAGkfEv3fHa9R6tvC2QAGSwKpThotAnfGlY5z0LThBO4ba_faEIzCdJOio_J4uOz9OdDFjCbajQ9od_gNlfytw80/s400/ss93.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>Proper letter spacing, yay</i></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
Compare this with this old screenshot, which has horribly messed up spacing:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOMvG8qbUEbs48nudtLwjEDYyl_OJFlMWD6Yz4JGQWYYMn-VWERnpTGnh3nf_L1hfXj7u5gY9vZhmLVT8I6JzD2B6dDSf99uRo-cN1jXXZUPxIXVmFnStyj0LoIvkUu1lr2lR_Ex7oOl4/s1040/ss53.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOMvG8qbUEbs48nudtLwjEDYyl_OJFlMWD6Yz4JGQWYYMn-VWERnpTGnh3nf_L1hfXj7u5gY9vZhmLVT8I6JzD2B6dDSf99uRo-cN1jXXZUPxIXVmFnStyj0LoIvkUu1lr2lR_Ex7oOl4/s400/ss53.png" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
So, that's all for this week. Sorry, no development video this week, just the little screen shake thing.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-71657298715359513772013-06-23T14:01:00.002-05:002013-10-08T11:39:13.729-05:00Slabs and LaddersHello! If you recall my previous update, there's a section about how I needed to make some enhancements to the layering system to allow for layer-over-layer scenarios. I put forward my plan for it and am happy to report things went pretty much exactly as planned. Here's a screenshot of the result:<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlAlmb-P79DEh_kHG7KCR8BlhExRXQZWrZ4HFWn4MaK2wuYb9IifnuYCsu1HjoQKEtO2anLGYFOfKVJH-agEYAAfKsGNvno_TGDP5AK-EJ3PnWIcfujSM2hXf0uMzHP71S0tYjnJj_T_U/s1600/ss84.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlAlmb-P79DEh_kHG7KCR8BlhExRXQZWrZ4HFWn4MaK2wuYb9IifnuYCsu1HjoQKEtO2anLGYFOfKVJH-agEYAAfKsGNvno_TGDP5AK-EJ3PnWIcfujSM2hXf0uMzHP71S0tYjnJj_T_U/s400/ss84.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>Layer-over-layer functionality: complete!</i></div>
<div>
<br /></div>
<div>
So now, I have the ability to create sections with multiple layer of gameplay. I haven't implemented leaping off edges yet, but it won't be difficult with how I've set up the infrastructure--it's pretty much just the reverse of climbing up a ladder.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
</div>
<div>
<br /></div>
<div>
This update isn't quite as flashy as the previous few, but it's pretty important from an engine standpoint because this feature is one of the last things I wanted to do before finalizing the <b>Section Data </b>structure. I've been holding off implementing <i>real </i>levels--that is, things that will go into the final game, not just demos--until this was complete, since anything I created before this would be invalidated (and force me to write data converters, which I don't feel like doing!)</div>
<div>
<br /></div>
<div>
That being said, check out the new level editor:</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRrOfzZ2r2hbw35USuijxTpenyzhOvHOmtWa_RH3mtbLG-_nYNVTmTML8jEPD_XMVWdIIJ1amyJY2Nlnz2HtfIXvDvtLQEexPymXAGMMd5Gd5JebTo39o2oa1rw-vmbJCv05lPoMqLf6c/s1600/ss85.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRrOfzZ2r2hbw35USuijxTpenyzhOvHOmtWa_RH3mtbLG-_nYNVTmTML8jEPD_XMVWdIIJ1amyJY2Nlnz2HtfIXvDvtLQEexPymXAGMMd5Gd5JebTo39o2oa1rw-vmbJCv05lPoMqLf6c/s400/ss85.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>A better looking editor with slab-switching support</i></div>
<div class="separator" style="clear: both; text-align: center;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQ1GRoWERDNAQrwi8ly-DX-a8LPN8NXRcxTValuKISKWC-7uFZ8kKU932XWqeTEUJEE3cm5uADnCBCNCt6OYcxWRQRl2oPoGGch3Yyt5mUZe1NzbuYysZNz0DFDDi3QeeQJ0fB8-XExJY/s1600/ss86.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQ1GRoWERDNAQrwi8ly-DX-a8LPN8NXRcxTValuKISKWC-7uFZ8kKU932XWqeTEUJEE3cm5uADnCBCNCt6OYcxWRQRl2oPoGGch3Yyt5mUZe1NzbuYysZNz0DFDDi3QeeQJ0fB8-XExJY/s400/ss86.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>Single-slab mode with models off</i></div>
<div class="separator" style="clear: both; text-align: center;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: center;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: left;">
I've put together a video of me showing off the results. Due to popular request, I've decided to use a mic instead of using annotations to describe what's going on, since it was hard to read annotations and pay attention to the screen at the same time. So make sure your sound is on!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/x4FMGat9leA?feature=player_embedded' frameborder='0'></iframe></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: left;">
Since the video does a pretty good job of showing what's going on, that's it for this week's blog update. Stay tuned! Allison (the artist) and I are going to be working on some serious character design (the current character is just temporary), so hopefully I'll be able to show off some of that next week.</div>
<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
</div>
<div>
<br /></div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-83519922241180556292013-06-10T17:18:00.001-05:002013-06-10T17:18:14.591-05:00Return from vacation!<div class="separator" style="clear: both; text-align: left;">
I've been in Europe for the past 9 days or so, which is why there wasn't any update this week. Obviously, I didn't really get much done, but I was able to do some old-fashioned level design. And I mean <i>really </i>old-fashioned: by sketching out maps in a notepad.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
So, with absolutely nothing else to offer for the last week, here's one of the sketches of one of the several immediately available to the player at the beginning of the game.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFBAVSwxzGncflL5CRBcHTogZoXjbA24qnwTW7u0qws9lMw_L1-HlrN5-G4JHyD_Y_MDV9SFCCfLCR49Zpbs8n1PZRRzYHFs04R8Ne5-K-GlubCqQdcYhSU_PiNjNx_LOMyXSBsneopok/s1600/ss77.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="273" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFBAVSwxzGncflL5CRBcHTogZoXjbA24qnwTW7u0qws9lMw_L1-HlrN5-G4JHyD_Y_MDV9SFCCfLCR49Zpbs8n1PZRRzYHFs04R8Ne5-K-GlubCqQdcYhSU_PiNjNx_LOMyXSBsneopok/s400/ss77.JPG" width="400" /></a></div>
<br />
Next up for this week: I'll be solidifying and finalizing the structure for <b>Layering</b>. The steps for this are as follows:<br />
<br />
<ul>
<li>The current system has a hard-coded <b>Layers </b>structure with a fixed number of <b>Tile Layers </b>and <b>Entity Layers. </b>These are hard-coded into the engine, which isn't good, because not every game is going to use the same layer structure. So, the engine will instead search for defined layers in the Implementation assembly and dynamically use those layers in the level editor and game engine.</li>
<li>The first bullet point is pretty easy, but this next one is going to be a major change. I want to allow for layer-over-layer scenarios: that is, not just a simple drawing order, but also entirely different <i>sets </i>of layers that overlap each other. So, let's say my game has 5 layers: ground layer 1, ground layer 2, entity layer 1, entity layer 2, and ceiling layer 1. But what if I want an entire section above another section? It would be very limiting to just create 10 hard-coded layers in the implementation assembly. Instead, I'm going to split the level structure into <b>Slabs</b> which each have a collection of <b>Layers</b>. Slabs will also serve as <i>physical </i>(that is, they affect game logic, not just drawing logic) separations of entities. A special entity behavior will transfer the player between slabs--this might occur, for example, at the top and bottom of a ladder. The end goal of slabs is to allow scenarios such as walkways that pass over other parts, and the ability to walk underneath those walkways.</li>
<li>Once slabs are complete, the lighting engine is going to have to be updated to support slabs correctly. A single layer of lights will no longer be sufficient. The bottom slab (closest to the ground) will receive light from all slabs, but upper slabs won't receive light from slabs underneath them.</li>
<li>Game logic needs to be updated such that the creation of entities is not done on a <b>Section</b>, but on a <b>Slab.</b> That is, the code 'section.CreateEntity(...)' is no longer valid, since the engine wouldn't know which slab to put it on. Instead, the command slab.CreateEntity(...) will be the way to spawn new entities dynamically.</li>
<li>Finally, I'll have to update the level editor so that the user can add and remove slabs, and switch which slab they're working on. It would also be nice to view just the current slab being worked on in isolation, or a full view of the level at once. This will probably be the most boring part of the update, but good tools are essential, so it's very important to do this correctly.</li>
</ul>
<div>
Will the update come this weekend? I don't know; this isn't a small feature, and it's definitely one I want to get right. I've been putting off <i>real </i>level design until this part was done, because it will change the structure of the file so much and I didn't want to waste time writing data migration utilities.</div>
<div>
<br /></div>
<div>
So, I'll see you when it's done! For more gradual updates, check my twitter, <a href="https://twitter.com/ericswheeler">https://twitter.com/ericswheeler</a></div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com3tag:blogger.com,1999:blog-648173414442845757.post-23191195504995242592013-05-27T22:28:00.001-05:002013-05-27T22:28:03.953-05:00An Explosive Update: Melon BombsOkay, I added a cool new item to the game, the Melon Bomb.<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5mrPDiO9y-B1RlsVsRtUx1fGLse5eU7MEOhgslxsGzkbk-FR2pAUDV8rS8WHnN9nkB57382-l3gx8sxOHl7U3HKw3lnquxX9NETAP_Po8cdDymsl6CVW4LBQaJ6nUKC7E5-v0812XLpI/s1600/bomb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5mrPDiO9y-B1RlsVsRtUx1fGLse5eU7MEOhgslxsGzkbk-FR2pAUDV8rS8WHnN9nkB57382-l3gx8sxOHl7U3HKw3lnquxX9NETAP_Po8cdDymsl6CVW4LBQaJ6nUKC7E5-v0812XLpI/s1600/bomb.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5mrPDiO9y-B1RlsVsRtUx1fGLse5eU7MEOhgslxsGzkbk-FR2pAUDV8rS8WHnN9nkB57382-l3gx8sxOHl7U3HKw3lnquxX9NETAP_Po8cdDymsl6CVW4LBQaJ6nUKC7E5-v0812XLpI/s1600/bomb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5mrPDiO9y-B1RlsVsRtUx1fGLse5eU7MEOhgslxsGzkbk-FR2pAUDV8rS8WHnN9nkB57382-l3gx8sxOHl7U3HKw3lnquxX9NETAP_Po8cdDymsl6CVW4LBQaJ6nUKC7E5-v0812XLpI/s1600/bomb.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5mrPDiO9y-B1RlsVsRtUx1fGLse5eU7MEOhgslxsGzkbk-FR2pAUDV8rS8WHnN9nkB57382-l3gx8sxOHl7U3HKw3lnquxX9NETAP_Po8cdDymsl6CVW4LBQaJ6nUKC7E5-v0812XLpI/s1600/bomb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5mrPDiO9y-B1RlsVsRtUx1fGLse5eU7MEOhgslxsGzkbk-FR2pAUDV8rS8WHnN9nkB57382-l3gx8sxOHl7U3HKw3lnquxX9NETAP_Po8cdDymsl6CVW4LBQaJ6nUKC7E5-v0812XLpI/s1600/bomb.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5mrPDiO9y-B1RlsVsRtUx1fGLse5eU7MEOhgslxsGzkbk-FR2pAUDV8rS8WHnN9nkB57382-l3gx8sxOHl7U3HKw3lnquxX9NETAP_Po8cdDymsl6CVW4LBQaJ6nUKC7E5-v0812XLpI/s1600/bomb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5mrPDiO9y-B1RlsVsRtUx1fGLse5eU7MEOhgslxsGzkbk-FR2pAUDV8rS8WHnN9nkB57382-l3gx8sxOHl7U3HKw3lnquxX9NETAP_Po8cdDymsl6CVW4LBQaJ6nUKC7E5-v0812XLpI/s1600/bomb.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5mrPDiO9y-B1RlsVsRtUx1fGLse5eU7MEOhgslxsGzkbk-FR2pAUDV8rS8WHnN9nkB57382-l3gx8sxOHl7U3HKw3lnquxX9NETAP_Po8cdDymsl6CVW4LBQaJ6nUKC7E5-v0812XLpI/s1600/bomb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5mrPDiO9y-B1RlsVsRtUx1fGLse5eU7MEOhgslxsGzkbk-FR2pAUDV8rS8WHnN9nkB57382-l3gx8sxOHl7U3HKw3lnquxX9NETAP_Po8cdDymsl6CVW4LBQaJ6nUKC7E5-v0812XLpI/s1600/bomb.png" /></a></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<i>The artist promises not everything will have skulls on it. But come on, it's a bomb.</i></div>
<div style="text-align: center;">
<i><br /></i></div>
<div style="text-align: left;">
<b>BUT </b>before I get to that and the accompanying video, I just wanted to point out that Super Obelisk is 100% rendered in OpenGL now. I have nothing but praise for the folks behind SlimDX, but in the end I wanted to open up the potential for ports to Mac/Linux, and consoles. The game feels best with a gamepad, so the push to consoles is a pretty attractive prospect.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Anyway, I'm using <a href="http://www.opentk.com/">OpenTK</a> now, which is a framework that includes C# bindings to OpenGL. This, combined with Mono (cross-platform implementation of C#/.Net) should make the porting process smooth.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
So, yeah, that took a bit of time, since I haven't touched OpenGL in many years, but overall it was a pleasant experience. I was pretty eager to get back into developing something concrete after getting things back to where they were, so I thought up the <b>Melon Bomb</b>, which is a bomb that happens to look like a melon.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
You can lay the bomb down. You can toss the bomb in front of you. Or, you can charge up a throw and launch it across the screen at your enemies! But why read about it when you can watch it all in action? As always, here's this weeks video. As always, best to open it up and put it in HD with annotations on, since they explain what's actually happening.<br />
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/QxGOtI8I8_U" width="420"></iframe>
</div>
<div style="text-align: left;">
<br />
No new infrastructure was required for the bomb update--just a new behavior and a new graphic asset. That's a good sign--that means engine development is slowing down and game implementation is speeding up!<br />
<br />
Until next time!<br />
<br /></div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com1tag:blogger.com,1999:blog-648173414442845757.post-36380804039382568452013-05-19T11:24:00.003-05:002013-05-19T11:24:35.719-05:00Framework conversionUnfortunately there's nothing fun to show this week, because I'm doing a conversion of my graphics engine from <b>SlimDX </b>to <b>OpenTK</b>--under the hood, this means Super Obelisk will use OpenGL instead of DirectX. <div>
<br /></div>
<div>
The reason I'm doing this now is to ease the process of potential porting. Thanks to the efforts of the folks behind <a href="http://www.mono-project.com/CSharp_Compiler">Mono</a>, I can continue to write the game in the language I love, C#, and still have the ability to port to Mac, Linux, and whatever other platforms (consoles, handheld) can run Mono. The problem is that DirectX is not supported on these platforms, and OpenGL is. I selected <b>OpenTK</b> based on the fact that it's what <a href="http://monogame.codeplex.com/">MonoGame</a> uses.</div>
<div>
<br /></div>
<div>
I haven't used OpenGL in many years (since college), and even then, my experience with it was fairly trivial, so I've been spending the last couple days learning the ropes. And by the 'ropes', I mean things like this:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5P-IZ7giK-WpMg9tyi9JnzsN7FLgfy_HNZzIA1nEGYVR4fuG60V9fSgdhpXeoTq3haQsSwjfN5Q1szRMr65leYYUYH_5m_o1GTqpIYaCx8PImFIcJBEE-akPS3XQ_Mv6lz9Wys3a2FWw/s1600/garbage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="271" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5P-IZ7giK-WpMg9tyi9JnzsN7FLgfy_HNZzIA1nEGYVR4fuG60V9fSgdhpXeoTq3haQsSwjfN5Q1szRMr65leYYUYH_5m_o1GTqpIYaCx8PImFIcJBEE-akPS3XQ_Mv6lz9Wys3a2FWw/s320/garbage.png" width="320" /></a></div>
<div style="text-align: center;">
<i>Super Obelisk: Now a game about a lonely cube in a strange world</i></div>
<div style="text-align: center;">
<i><br /></i></div>
<div style="text-align: left;">
I'm a bit further along than that now and I'm ready to actually convert my codebase to the new framework, so that's what I'll be doing today.</div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-79226964592743793922013-05-12T12:31:00.002-05:002013-05-12T12:32:57.686-05:00Rain and the Blob EnemyWelcome back! I have a lot of neat things to show off this week! Video is at the end of the post if you want to skip straight to that.<br />
<br />
<b>1. </b>First up is a <b>Rain Effect</b>. This actually required very new little new engine infrastructure to create. I had to implement <b>Texture Offset</b> to actually animate the rain. Instead of using particles for the individual falling drops, it's just a big rain texture repeated over and over and shifted every frame to create the illusion of falling rain. The video at the end of this post shows the evolution of the rain effect.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbVTlSlPoTyTGmY_ZZlI4t0WJ0r6XZsF9ABYlygPFoHEs83uGWxd7yUJIvQmd7thn7A1qve1OTy73_BcVZJKBSmN8bJLD-dkSrXCD29R8dI2pB2dO4DP1XH0f_AQmPPLC-LSnyJgKqwPY/s1600/ss70.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbVTlSlPoTyTGmY_ZZlI4t0WJ0r6XZsF9ABYlygPFoHEs83uGWxd7yUJIvQmd7thn7A1qve1OTy73_BcVZJKBSmN8bJLD-dkSrXCD29R8dI2pB2dO4DP1XH0f_AQmPPLC-LSnyJgKqwPY/s400/ss70.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>It's rainy</i></div>
<br />
<b>2. </b>The return of the <b>Fade Transition</b>. You might remember from previous videos that this had existed at one point, but I lost it in the infrastructure conversion (Lua --> C#). You can see the fade transition in the video about halfway through, when I enter the temple.<br />
<br />
<b>3. </b>A <b>Blob</b> <b>Enemy</b>. I don't have a name for this thing yet, so let's just call it Blob. Look at it. Look at that thing chomp.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZXFJvN0Q0_MD04y_tScYdr-uwfL9loDCnfhVLT8_DXmMZ0J_zy0FurJzoO40_IWgjoTKE12bvb8_I3cUg0XCs9n80ML_8kvM8eq2DB9WC93z360JJOS3P3VJSlF1g73Prv_o14hTdoA/s1600/chomp.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZXFJvN0Q0_MD04y_tScYdr-uwfL9loDCnfhVLT8_DXmMZ0J_zy0FurJzoO40_IWgjoTKE12bvb8_I3cUg0XCs9n80ML_8kvM8eq2DB9WC93z360JJOS3P3VJSlF1g73Prv_o14hTdoA/s1600/chomp.gif" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZXFJvN0Q0_MD04y_tScYdr-uwfL9loDCnfhVLT8_DXmMZ0J_zy0FurJzoO40_IWgjoTKE12bvb8_I3cUg0XCs9n80ML_8kvM8eq2DB9WC93z360JJOS3P3VJSlF1g73Prv_o14hTdoA/s1600/chomp.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZXFJvN0Q0_MD04y_tScYdr-uwfL9loDCnfhVLT8_DXmMZ0J_zy0FurJzoO40_IWgjoTKE12bvb8_I3cUg0XCs9n80ML_8kvM8eq2DB9WC93z360JJOS3P3VJSlF1g73Prv_o14hTdoA/s1600/chomp.gif" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZXFJvN0Q0_MD04y_tScYdr-uwfL9loDCnfhVLT8_DXmMZ0J_zy0FurJzoO40_IWgjoTKE12bvb8_I3cUg0XCs9n80ML_8kvM8eq2DB9WC93z360JJOS3P3VJSlF1g73Prv_o14hTdoA/s1600/chomp.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZXFJvN0Q0_MD04y_tScYdr-uwfL9loDCnfhVLT8_DXmMZ0J_zy0FurJzoO40_IWgjoTKE12bvb8_I3cUg0XCs9n80ML_8kvM8eq2DB9WC93z360JJOS3P3VJSlF1g73Prv_o14hTdoA/s1600/chomp.gif" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZXFJvN0Q0_MD04y_tScYdr-uwfL9loDCnfhVLT8_DXmMZ0J_zy0FurJzoO40_IWgjoTKE12bvb8_I3cUg0XCs9n80ML_8kvM8eq2DB9WC93z360JJOS3P3VJSlF1g73Prv_o14hTdoA/s1600/chomp.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZXFJvN0Q0_MD04y_tScYdr-uwfL9loDCnfhVLT8_DXmMZ0J_zy0FurJzoO40_IWgjoTKE12bvb8_I3cUg0XCs9n80ML_8kvM8eq2DB9WC93z360JJOS3P3VJSlF1g73Prv_o14hTdoA/s1600/chomp.gif" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZXFJvN0Q0_MD04y_tScYdr-uwfL9loDCnfhVLT8_DXmMZ0J_zy0FurJzoO40_IWgjoTKE12bvb8_I3cUg0XCs9n80ML_8kvM8eq2DB9WC93z360JJOS3P3VJSlF1g73Prv_o14hTdoA/s1600/chomp.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaZXFJvN0Q0_MD04y_tScYdr-uwfL9loDCnfhVLT8_DXmMZ0J_zy0FurJzoO40_IWgjoTKE12bvb8_I3cUg0XCs9n80ML_8kvM8eq2DB9WC93z360JJOS3P3VJSlF1g73Prv_o14hTdoA/s1600/chomp.gif" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Okay, so the source material is pretty cool. But this enemy represents a key development milestone: this is a <i>real enemy </i>with real behaviors. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Generally my engine development pattern is to attempt to make realistic game scenarios and use them to discover what the engine still needs to make them work. There's a popular saying in game development circles: <i>make games, not engines</i>. This doesn't really mean that you shouldn't make an engine, but it does mean that you shouldn't make an engine in a vacuum--that is, an engine without test cases to drive it will probably end up being useless when it comes to practical application.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
So, anyway, back to the blob. The blob has a more complex state machine than the previous demo enemies (spike, ghost) I've created. This led to some issues where state management was difficult when states were <i>interrupted</i> and various animations hadn't completed yet. For example, when you get near a blob, it compresses before jumping at you. If you hit it during this animation, it gets sent into another state (knockback) before the animation completes. These effects are achieved with entity <b>controllers</b>, as shown in a <a href="http://superobelisk.blogspot.com/2013/01/blowing-up-balls-setting-entity.html">previous blog post</a>. After the compression effect of the blob, it has a command that sends it into an 'jumping' state. We don't want this to run anymore if the blob was interrupted by an attack (and sent into the knockback state). To solve this, I introduced <b>state-local controllers</b>. That is, they are controllers that are discarded if the state changes, since they're 'owned' by the current state. This makes for a much cleaner programming model.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
This is sort of hard to explain without code examples, so look for a post later in the week which shows the blob source code with an explanation of how it works.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>4. Hue Shift</b></div>
<div class="separator" style="clear: both; text-align: left;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: left;">
In the video, you'll see the blob flash colors when it's hit. This is actually done with a pixel shader that shifts the hue of the entity, rather than attempted to just change the color of the vertices (which doesn't work--a green image with red vertices appears black).</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3RsO-x3Unb0S1gRs9dDupWHKSgmLhvt2q5F0GYe9ahyphenhyphenllJbYC9dkwtm6ycGFjgyyWVTt7qQpi1NDiMNqWzCZizr8o-9qlAMF898abcz0bH8G7kIQYzpFj8oLAfVsyJAgVorluOvJ6cx8/s1600/ss71.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3RsO-x3Unb0S1gRs9dDupWHKSgmLhvt2q5F0GYe9ahyphenhyphenllJbYC9dkwtm6ycGFjgyyWVTt7qQpi1NDiMNqWzCZizr8o-9qlAMF898abcz0bH8G7kIQYzpFj8oLAfVsyJAgVorluOvJ6cx8/s320/ss71.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>Hue shifting the blob</i></div>
<div class="separator" style="clear: both; text-align: center;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: left;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: left;">
Anyway, here's the video. Enjoy! Recommended HD/fullscreen/annotations on.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/jRNwz3zezCc" width="420"></iframe>
</div>
<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-30832535072631794882013-05-04T01:35:00.003-05:002013-05-04T01:53:43.785-05:00Adding Player HealthVideo is at the very end of the post in case you want to skip straight to it.<br />
<br />
Two posts ago I introduced a new <b>Screen Management </b>architecture that I had implemented. Currently, Entity state can be easily managed and manipulated by using <b>Behaviors. </b>Additionally, <b>S</b><b>ections </b>can be created and destroyed (and rendered at the same time, with different cameras). But what if two <b>Sections</b> need to communicate to each other? For example, <i>Player Health</i> is something that both the game screen (so enemies can reduce it) and the HUD screen (so it can be displayed) need to know about!<br />
<br />
<div style="text-align: center;">
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQsvVwUOyXZNvyOahr6zZIEE1xWEDPWMGyQ4_HORdW1ilbzOUOnGO2VYLgRtzFWBn8YdiryBLaiHmSapRgdfVo42atM1lWyAdUhQbQz0GAHh6utpn9tSj0c2FUG0mHVtS8-gQqX_iGKtg/s1600/ss64.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="153" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQsvVwUOyXZNvyOahr6zZIEE1xWEDPWMGyQ4_HORdW1ilbzOUOnGO2VYLgRtzFWBn8YdiryBLaiHmSapRgdfVo42atM1lWyAdUhQbQz0GAHh6utpn9tSj0c2FUG0mHVtS8-gQqX_iGKtg/s400/ss64.png" width="400" /></a></div>
<br /></div>
<div style="text-align: center;">
<i>Both 'Sections' need to know about a shared variable, Health.</i></div>
<br />
<b>Entities </b>are local to a section and shouldn't be passed around, so we don't really want to use a behavior attached to an entity to do our work.<br />
<div>
<br /></div>
<div>
One option is to use a <b>Global </b>state object of some sort. But that's no good, because globals are generally difficult to manage and lead to poor design. For example, if I wanted to load a game, I'd have to manually implement a 'reset' on the game state. With proper object management, I should be able to just toss out the existing game state and replace it with a fresh one. In addition, a global state would imply nonsensical designs where you could access the player's health from the title screen. So, no to globals.</div>
<div>
<br /></div>
<div>
Another option is to tie a <b>Game Model </b>(this can be any object you want) to a <b>Section</b>, but allow the model to be shared across sections. This is the design I ended up implementing. Here is an example of how the main game might be set up with a shared model:<br />
<div style="text-align: center;">
<i><br /></i>
<br />
<div class="separator" style="clear: both; text-align: center;">
<i><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4crEijQmqTSYiy9n2epgQkznkStxP8DfKI-UN0sM-XdNo9ONXCTI6NE-gaGpOhY2EA3fh4FAhofBb1sd0GRXdm2XKoLoQc3QuNRC-NTGZfxOAUQV15PoLzEUzhC-SYQKNAav0M9g8GGQ/s1600/ss65.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4crEijQmqTSYiy9n2epgQkznkStxP8DfKI-UN0sM-XdNo9ONXCTI6NE-gaGpOhY2EA3fh4FAhofBb1sd0GRXdm2XKoLoQc3QuNRC-NTGZfxOAUQV15PoLzEUzhC-SYQKNAav0M9g8GGQ/s400/ss65.png" width="400" /></a></i></div>
</div>
<div style="text-align: center;">
<i>The code that sets up a simple shared Game Model</i></div>
<br />
Once this is done, <b>Behaviors </b>can access the <b>Game Model</b>. For the sake of convenience, I've decided to introduce a base class for behaviors that belong in-game (as opposed to, say, stuff on a start-up screen). Here is a sample (and simple) usage:<br />
<br />
<div style="text-align: center;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxBAP28fNRJt8yWdw_3k8DUxL9J1won58uHWTi6iMYnZQstw0NLqgs3k3XkvgY9wyZ3QYHzloYWgdQ4KLF56yu7ykq96oKV4jKs2Wz5yAZcbMYdwMawaRRs7-2vLa4mmeUmdbOD3EDCNA/s1600/ss66.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="283" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxBAP28fNRJt8yWdw_3k8DUxL9J1won58uHWTi6iMYnZQstw0NLqgs3k3XkvgY9wyZ3QYHzloYWgdQ4KLF56yu7ykq96oKV4jKs2Wz5yAZcbMYdwMawaRRs7-2vLa4mmeUmdbOD3EDCNA/s400/ss66.png" width="400" /></a></div>
<br /></div>
<div style="text-align: center;">
<i>Highlighted is the code that makes the player lose health. Simple!</i></div>
<div style="text-align: center;">
<i><br /></i></div>
<div style="text-align: left;">
Note that I've added a 'damage amount' variable to the 'DamagePlayer' trigger. So now what? Well, I've created some <b>Hearts </b>that live in the <b>HUD Section.</b> Each Heart has an update method that polls the game model to determine how it should be displayed. For example, if the current health is 5, and the heart is the 7th heart, the heart should be invisible. If the current health is 5.5, and the heart is the 6th heart, then we'd show a partial heart (for the sake of simplicity, I just draw it at half-scale).</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: center;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5whQVqbxUvahyZatLOtBsPeaS4TNcc6hiG9GEfUbRvJT-rB-xO-PfNyEf5SSYjRLR955XkrVPv08OvxRgm6HLDIXLBQZqvEoppGkmg-qIaxt51S8mdK83X5ucFY10TCaRmb2wMnOcQ1k/s1600/ss67.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="78" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5whQVqbxUvahyZatLOtBsPeaS4TNcc6hiG9GEfUbRvJT-rB-xO-PfNyEf5SSYjRLR955XkrVPv08OvxRgm6HLDIXLBQZqvEoppGkmg-qIaxt51S8mdK83X5ucFY10TCaRmb2wMnOcQ1k/s400/ss67.png" width="400" /></a></div>
<br /></div>
<div style="text-align: center;">
<i>The player has 5.5 health remaining</i></div>
<div style="text-align: center;">
<i><br /></i></div>
<div style="text-align: left;">
As always, there is a fun little video of everything in action. Some notes:<br />
<ul>
<li>As a demo of both subtracting and adding health, I've added a simple little ghost enemy that does damage proportional to its size <i>and </i>little heart pickups. The ghost in the first room does 1 damage, the bigger ghosts do 2.5 damage. The heart pickups restore 1 health.</li>
<li>The model caps the player's health at 8 for this demo. You can see that additional heart pickups, once full, don't give the player more health.</li>
<li>I'll be adding game music to the videos just for flavor. This is being played through the game's audio engine, which I added recently (it wasn't worth a blog post--it's pretty simple for now). Of course, once I get my own music I'll be using that!</li>
<li>The ghost enemy is just a demo whipped up in a few minutes, nothing necessarily permanent. True enemy design will come at a later phase.</li>
<li>I had to re-implement section transitions after changing from Lua to pure C#, but hadn't gotten around to actually doing it until this week. </li>
</ul>
<div>
Anyway, the video. Enjoy!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/LMUq5JdiC-g?feature=player_embedded' frameborder='0'></iframe></div>
<div>
<br /></div>
</div>
<div style="text-align: left;">
<br /></div>
</div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-16053725801597923692013-04-24T00:23:00.001-05:002013-04-24T00:23:04.419-05:00How To Make StuffSo, if you've been following my progress, you might remember something like this from long ago:<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnG8oeoMR2LhIUmnnHXArP6S8Qi9tdm3RyAH4SprphcJIHT7Ctk64vZ93LB-t3rJzGjIi1N-Vmxym_sUveGPpThsIH-JfA48l6HzmOiy4p1eFr2lkCfzmNxPsGGJ-7V7pLXLroqW0d930/s1600/ss22.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="251" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnG8oeoMR2LhIUmnnHXArP6S8Qi9tdm3RyAH4SprphcJIHT7Ctk64vZ93LB-t3rJzGjIi1N-Vmxym_sUveGPpThsIH-JfA48l6HzmOiy4p1eFr2lkCfzmNxPsGGJ-7V7pLXLroqW0d930/s400/ss22.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>My first script</i></div>
<div class="separator" style="clear: both; text-align: center;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: left;">
What's depicted here is me editing the behavior of an object--I think it was a bush--directly in the level editor. Pretend for a moment that it was actually a <i>useful </i>script, like describing how the bush spawns a bunch of leaves and then disappears when the player slashes it.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Obviously an inline script editor is not going to suffice if there's hundreds or thousands of these bushes in the game, since I'd have to copy the script everywhere. And then if I needed to make changes to the script, I'd need to update the copy everywhere. This is similar the 'don't repeat yourself' philosophy of programming: common behaviors should be abstracted to one place.</div>
<div>
<br /><div>
When I moved away from Lua and into full C# (see <a href="http://superobelisk.blogspot.com/2013/04/player-takes-damage-retaliate.html">this blog post</a>), I needed a way to bind entities in the level editor to behaviors in C#. Just to get things up and running so I could experiment with the model, I implemented a quick hack which looked something like this:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivRTx2BJe1QyGYJHrGdMJm6DSwNQjso0U0OsgIFS2KmvxjAG7V_76BIMiaJulPQ93Yrs-d85G7hQBGXnGae0ckzebwvoHduev87nzy4PR_zuWuWxW5_wv50JI0-NKVNZLt6MKm53NA6yo/s1600/ss60.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="420" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivRTx2BJe1QyGYJHrGdMJm6DSwNQjso0U0OsgIFS2KmvxjAG7V_76BIMiaJulPQ93Yrs-d85G7hQBGXnGae0ckzebwvoHduev87nzy4PR_zuWuWxW5_wv50JI0-NKVNZLt6MKm53NA6yo/s640/ss60.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>Just a hack to get things going, not a feasible long-term strategy.</i></div>
<div>
<br /></div>
<div>
So, basically, I was attaching behavior to entities based on the texture of the entity, and in one case, parsing the tags of the entity to differentiate between behaviors. Terrible! But this was just temporary. So over the past couple days I've implemented it the correct way.</div>
<div>
<br /></div>
<div>
Now, <b>Behavior Templates </b>can be picked directly in the level editor! That means we can write a template in the <b>Implementation </b>assembly and it will instantly be available in the level editor:</div>
<div>
<br /><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQ6K9BXwiTNvhBYLUd_pYdi179lkczRaCs7wwAFGarOzLMq5esOkvwQmCQrf25wf0kXkG1EJBCXMlQdW-tTc1gl37ZRl2J1YuFlr5nkpCuCczjZPZCsx4g2PmyMRTBK2F739T-5X5gyz4/s1600/ss61.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQ6K9BXwiTNvhBYLUd_pYdi179lkczRaCs7wwAFGarOzLMq5esOkvwQmCQrf25wf0kXkG1EJBCXMlQdW-tTc1gl37ZRl2J1YuFlr5nkpCuCczjZPZCsx4g2PmyMRTBK2F739T-5X5gyz4/s400/ss61.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
What's even better, I can add custom properties to the template in code...</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq4ZhPXyXSz3rJa3n1bdl3feFCrWgAo87csmE2dq-vBfJyFRnAbWBODO_J3UvZ4gUbo2uvhKAYhRqwglBFncgCVAfHGxapW7Oj5TuJdM0XJekMlxa_ZWHQ5MQSArQ5rzI1mMv2anbFHc8/s1600/ss62.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="47" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgq4ZhPXyXSz3rJa3n1bdl3feFCrWgAo87csmE2dq-vBfJyFRnAbWBODO_J3UvZ4gUbo2uvhKAYhRqwglBFncgCVAfHGxapW7Oj5TuJdM0XJekMlxa_ZWHQ5MQSArQ5rzI1mMv2anbFHc8/s400/ss62.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
...and have them show up as editable fields (with possible default values--use the checkbox to override) in the editor:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ-6hT3HGUCllZQ1_ODph6v8VqanANTtp7xoWxDAebVSNpJrUri40-3P2TLKQBQSmBHeZLjii5GzTQbQJdtXuTYheBkS7kfxZh3LUV7J_DkDvByoHZYkIOZKDA56R-ECn7WWNcjZT3gIM/s1600/ss63.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="336" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ-6hT3HGUCllZQ1_ODph6v8VqanANTtp7xoWxDAebVSNpJrUri40-3P2TLKQBQSmBHeZLjii5GzTQbQJdtXuTYheBkS7kfxZh3LUV7J_DkDvByoHZYkIOZKDA56R-ECn7WWNcjZT3gIM/s400/ss63.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
So, now I have a pretty good system for designing reusable behavioral entities and them placing them in levels via the level editor. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I put together a short video of the process for <b>Adding New Stuff</b>, from start to finish. In the video, I take a sample graphic of a ball and create a custom behavior for it with a few properties--which can then freely be used on any level in the game--in just a few minutes. Check it out! Also, make sure annotations are on and you'll probably need HD/fullscreen to see the code.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/QBBI0v8zbr8?feature=player_embedded' frameborder='0'></iframe></div>
</div>
<div>
<br /></div>
</div>
<div>
That's all for now. Back to screen communication and making those hearts react to the player taking damage!</div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-11575962384835419002013-04-21T20:34:00.002-05:002013-04-21T20:34:38.698-05:00Screen ManagementAn important part of developing a game (and engine) is a robust system for screen management. My desire to add a basic 'player health' next led to the obvious requirement to actually display that health, but I hadn't developed any sort of HUD (head-up-display) system yet.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiER7sGRr59VibG1kNK34-JUXf64yfAOdMQ0y9946kHuxPOYXj1ptp_48IUVowlqVQ5L7lbG-RBAHeOumldvHwXLrlpn27viLoY7zSTz-HJVupz7y5hdJftEYaAdUhd_diwKlS8xi-FjPY/s1600/ss54.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiER7sGRr59VibG1kNK34-JUXf64yfAOdMQ0y9946kHuxPOYXj1ptp_48IUVowlqVQ5L7lbG-RBAHeOumldvHwXLrlpn27viLoY7zSTz-HJVupz7y5hdJftEYaAdUhd_diwKlS8xi-FjPY/s320/ss54.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>How much health do I have left? Where am I?</i></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
There's nothing inherently complex about developing a HUD compared to other elements in the game. In a way, it's even simpler, because the HUD elements don't move that much, don't collide, and don't need too much programming behind them; presumably they're just interface elements (like health) that update their display based on some sort of background model (the game state). But what about moving around and animating these elements?<br />
<br />
I realized quickly that there's no reason not to leverage <i>all </i>of my existing infrastructure for new screens. Although the 'Sections' (levels) in Super Obelisk are designed in the editor and loaded from disk, this is merely a convenience--Sections can be generated on-the-fly in code, and entities that can move, animate, create other entities, and react to input can be dynamically added. So I decided that this dynamic creation would be used to create Sections that serve other purposes besides gameplay!<br />
<br />
I actually decided to tackle a very simple screen management task first: pausing the game. Check the video below for a very short demo of...well, pausing. I know, it's not super exciting, but a lot of game development work isn't that flashy.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/-eyyw8xTlV8?feature=player_embedded' frameborder='0'></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<i>Feel the thrill of watching a game get paused multiple times in mere seconds</i></div>
<div class="separator" style="clear: both; text-align: center;">
<i><br /></i></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
So, what does this look like underneath the hood?</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>The <b>IGameInterface </b>interface, available from any <b>BehaviorTemplate </b>(see previous blog entries, this is the code that controls all game logic), now supports a <b>NewSection </b>method that pushes a new <b>Section </b>onto a list of Sections that the main game loop controls. Theoretically, you could use this to divide the screen up into 4 quadrants and play 4 totally separate games at once (or, if the cameras overlapped, they'd just kind of all merge into each other)</li>
<li>So, when the player presses <b>Start</b>, a helper class called 'PauseScreen' with a single method 'Create'--which takes in an instance of the current section and the <b>IGameInterface</b>--creates a 'Pause' Section. It also calls a special 'pause' method on the <i>existing </i>section (the gameplay) which tells the engine to stop updating entities.</li>
<li>The helper class adds a few entities to the Pause section. A transparent black solid rectangle that fills the entire view (which makes it darker), some text that says 'Paused' (with a fancy entrance--see the previous blog post), and an invisible entity which will handle input.</li>
<li>The invisible entity is given an <b>Update</b> handler which will react to the player pressing <b>Start </b>again by unsetting the 'pause' property on the gameplay section, and destroying the current section.</li>
</ul>
<div>
And that's it! For those who are code-inclined, here is the entire source code for what I just described.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPASGB1OkJc5Zwtyx0Kqr7BDxiYsd67A6tkE1nXdQOFVEWptkxe3SxWj4VNP5e35cqCXqbj1IBAN59ciHDxLlRehC4lC3bv7hbrp5lMlnCAd6vAYErP1cmaIotfztD1rR7m_UP8QHsqTQ/s1600/ss55.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPASGB1OkJc5Zwtyx0Kqr7BDxiYsd67A6tkE1nXdQOFVEWptkxe3SxWj4VNP5e35cqCXqbj1IBAN59ciHDxLlRehC4lC3bv7hbrp5lMlnCAd6vAYErP1cmaIotfztD1rR7m_UP8QHsqTQ/s320/ss55.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDBwoulMyQnf_YbrLV4i9Nal5A2FmiXpEBbLn8hRFKJZHKue6SE79sFmFc_K6MLEt6TGVs2INiWq-AdEOFpLKPCxkkEbFbeBgcTyxh72eMFM5dzOeB-ke-f4MAaSkIpF6oD1pUrUH-GXE/s1600/ss56.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="291" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDBwoulMyQnf_YbrLV4i9Nal5A2FmiXpEBbLn8hRFKJZHKue6SE79sFmFc_K6MLEt6TGVs2INiWq-AdEOFpLKPCxkkEbFbeBgcTyxh72eMFM5dzOeB-ke-f4MAaSkIpF6oD1pUrUH-GXE/s320/ss56.png" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
I've used these enhancements to the infrastructure to create a very simple HUD with a few hearts in the top-right corner. But when does a HUD get created? Shouldn't it always be there with the game? In almost all cases, yes. So, at the <b>Entry Point </b>for the game (which will, in the future, create a Section for a startup screen), I create two sections: the level (hard coded for now, or provided by the editor), and the HUD. Behold, the world's ugliest HUD until I get proper graphics for it:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAMisOkSeN48Knf6aZ7F17mj83cwyuYRmldlSRfqbz7uIxuJwpeK0trr7uEMZ11aqppZbEs24DUk1lEnJeA9MEuqQ0BxxnPcysQsdNRfrP7J8josWN6GNYFaxaAFt4XASIUiAATTNBee0/s1600/ss57.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAMisOkSeN48Knf6aZ7F17mj83cwyuYRmldlSRfqbz7uIxuJwpeK0trr7uEMZ11aqppZbEs24DUk1lEnJeA9MEuqQ0BxxnPcysQsdNRfrP7J8josWN6GNYFaxaAFt4XASIUiAATTNBee0/s400/ss57.png" width="400" /></a></div>
<div>
<br /></div>
<br />
So, back to what started this in the first place: I have a health bar now, so...what is it displaying? Why are there 4 hearts? Well, right now, it's because I hard coded 4 hearts in there. So, how do I get <i>real game data</i>--the player's health, inventory, number of times they've died, the status of all of the bosses, the walls you've blown up, and a myriad of other various bits of info, both temporary and persistent--from a section? Do sections communicate with each other?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrW2wfgK7I_CoHWNejABFto9Pmu1BpNYQvFpV14Hsc-xXvsycicEb-DEaCFU7qJ1f0ZaJcUCoTt8BTEVO-wZ4Yy9Yc5YWgnVr_i1wwdOFuCKNENDPFGPOrwE6FHNTrc_Zro9n05bEu-aQ/s1600/ss58.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrW2wfgK7I_CoHWNejABFto9Pmu1BpNYQvFpV14Hsc-xXvsycicEb-DEaCFU7qJ1f0ZaJcUCoTt8BTEVO-wZ4Yy9Yc5YWgnVr_i1wwdOFuCKNENDPFGPOrwE6FHNTrc_Zro9n05bEu-aQ/s320/ss58.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i>Who owns the Game Model and how is the model implemented? Does the main game instance own a single model (red line), or do sections have access to it directly (gray lines)?</i></div>
<br />
<br />
I don't think so. A better approach is to have a <b>Game Model </b>of some sort that<b> </b>Sections can access. I'll be tackling this architecture problem over the next few days, which should result in a demo of my player actually taking damage until they run out of health! Stay tuned!<br />
<br />
<br />Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-55149955382487790882013-04-16T22:37:00.000-05:002013-04-16T22:38:58.754-05:00Fun with Fonts<div style="text-align: center;">
The picture says it all:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglAkKeAry23TA5WK1vJzW2twA9iP1_uFn0FrXXLY4Ko1i1V1b-0vdU2Qsiz24Eq2uWem-ot9ktWBK7sJBUmn5RbEMX2YHXGwII88zv1fQjVbwIo4iSwn7bSCsS8_zZML_AR581RFaEekw/s1600/ss53.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="496" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglAkKeAry23TA5WK1vJzW2twA9iP1_uFn0FrXXLY4Ko1i1V1b-0vdU2Qsiz24Eq2uWem-ot9ktWBK7sJBUmn5RbEMX2YHXGwII88zv1fQjVbwIo4iSwn7bSCsS8_zZML_AR581RFaEekw/s640/ss53.png" width="640" /></a></div>
<br />
<br />
...well, not really. It says what this post is about, but it certainly doesn't show everything! As always, there's a video for that! Make sure you watch in a large viewer and in HD, as it might be difficult to read the fonts on the screen (which serve as annotations) in a small viewer.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i.ytimg.com/vi/30PTT_OIhr0/0.jpg" height="266" width="320"><param name="movie" value="http://www.youtube.com/v/30PTT_OIhr0?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/30PTT_OIhr0?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
So, how does this work? Easy...for now. The <i>current </i>implementation--but almost certainly not final--is to use a single texture source for the entire font. It looks like this:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGuT7rFJDkLwDAmGEAaQxJigyzTQFkce4kxfRApFh-y1jt0LXjOgufzfjbxIjrY-oZkBrtjn4YQhUM0vINlTTiniTUNzqiwNwVBYQWrScMHDZQKB2iP0pArsuXZECLCrtu3xbOQUwMURo/s1600/fontSmall.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGuT7rFJDkLwDAmGEAaQxJigyzTQFkce4kxfRApFh-y1jt0LXjOgufzfjbxIjrY-oZkBrtjn4YQhUM0vINlTTiniTUNzqiwNwVBYQWrScMHDZQKB2iP0pArsuXZECLCrtu3xbOQUwMURo/s320/fontSmall.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
So, I wrote a quick utility to create a texture with one frame per letter (it could also be implemented as a bunch of textures, but it doesn't make any difference--the frame version is slightly easier from a coding standpoint). Once this was done, there were actually no new features required in the engine! Just a small helper function that creates the entities for you given a string. And that's it. All of the effects you see--including the final one where I slash the letters away with my sword--are just entity features that can be found in previous posts and videos.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
This is a nice start, but there are a couple problems. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
One, I would like to be able to use <i>any</i> font, not just this pre-built one. This would likely be accomplished by setting up a pool of available fonts at design-time, and then rendering the characters of that font to an texture at run-time (that is, when the game begins). So, there is never an actual graphics file for a font (that I own, at least--of course, the operating system has a file somewhere).</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Two, the <a href="http://en.wikipedia.org/wiki/Kerning">kerning</a> is non-existent with the current method. Kerning information is available via the windows API, and it shouldn't be too difficult to use (just a slight modification of the helper method) to properly space the entities once I have it.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
However, this will suffice for now, and I'll come back to these features at another time. The fonts may not look perfect, but they can do some cool things!</div>
<div class="separator" style="clear: both; text-align: left;">
Note: The font in the upper left corner showing diagnostic information is rendered in a different (less flexible) way, so this is definitely a new feature.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<br />
<br />
<br />Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-52794130388115099292013-04-14T19:25:00.001-05:002013-04-14T19:25:03.359-05:00Fight the DarknessI know I said I'd get into something like a health meter for enemies this time, but I got a bit sidetracked. I added lighting! And a boomerang, and jumping! A few screenshots, but be sure to watch the video at the bottom.<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAsdqkVVImdTc8zYq8zoMcYLjAaF7IjlGblwrHDHDxqnRNHrFUY2wLeEzeMQNNSlLHY2cSJeXn_NnmUbEnmoiQRy_N6Q7XzJ237dHC6__86n5o6oGi7BGBl0SK166uDg55QWAHNkGOOv0/s1600/ss50.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="496" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAsdqkVVImdTc8zYq8zoMcYLjAaF7IjlGblwrHDHDxqnRNHrFUY2wLeEzeMQNNSlLHY2cSJeXn_NnmUbEnmoiQRy_N6Q7XzJ237dHC6__86n5o6oGi7BGBl0SK166uDg55QWAHNkGOOv0/s640/ss50.png" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNujzYG0B11GXIbCWhlcO0yPwWg7lC3_pCYJ6_np9ItZIzQoo3v4bSfDcVm-2rSF5ezMRu8KI3z0W5Vr_sp-ahrC3K7pkzbtcsv0jklIM_bcPk1G3vSbPYyRPgDSXjMkH7sdLv-A4M9dU/s1600/ss51.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="494" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNujzYG0B11GXIbCWhlcO0yPwWg7lC3_pCYJ6_np9ItZIzQoo3v4bSfDcVm-2rSF5ezMRu8KI3z0W5Vr_sp-ahrC3K7pkzbtcsv0jklIM_bcPk1G3vSbPYyRPgDSXjMkH7sdLv-A4M9dU/s640/ss51.png" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrluomQo4HrLtNGbQo4Wo17x1y8w2Xv76TkTgF0pU0eFubwbxlvg9yZ9IWVsU7R253e2WTB_Bj52e1FkILPRsPu7G0yurUA-dLUAvWPPljzXFJl6Qs9BHopyWEQV6fKBP-83EU7snYHA4/s1600/ss52.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="496" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrluomQo4HrLtNGbQo4Wo17x1y8w2Xv76TkTgF0pU0eFubwbxlvg9yZ9IWVsU7R253e2WTB_Bj52e1FkILPRsPu7G0yurUA-dLUAvWPPljzXFJl6Qs9BHopyWEQV6fKBP-83EU7snYHA4/s640/ss52.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<br /></div>
<div>
<div>
Lights are simply entities on a special layer that's marked as a 'light layer'. Like other entities, they can be manipulated in a variety of ways, use any texture and color, etc. This week's video will show off some of the features. Check it out!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/BXgs22SCXXk?feature=player_embedded' frameborder='0'></iframe></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Hopefully I can throw together a more technical blog post to explain the lighting if anyone is interested, but for now I'm out of time. Until next time!</div>
</div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0tag:blogger.com,1999:blog-648173414442845757.post-75085208711854031822013-04-06T18:48:00.002-05:002013-04-06T18:48:10.585-05:00Player Takes Damage! Retaliate!Okay! Big update from a technical standpoint, small update from a gameplay standpoint. Warning, if you don't really care much about technical stuff, you might want to scroll down to the second screenshot and start from there!<div>
<br /></div>
<div>
In my previous post, I demonstrated how a simple 'spike' enemy might be programmed, and provided the Lua scripts that control its behavior. Well, sometime in the middle of coding those behaviors, I realized how difficult creating robust code for more complex behaviors is going to be. So, I took a step back and asked myself 'why are these behaviors in Lua?'</div>
<div>
<br /></div>
<div>
I originally chose Lua as a scripting language for several reasons. It's lightweight, popular (not a reason in itself, but it generally means more community support), relatively fast, and easy to use. But writing extensive game logic in scripts beyond basic sequential commands has a number of disadvantages:</div>
<div>
<ul>
<li>Debugging is difficult in scripting languages</li>
<li>Development is a more tedious process, since you don't get intellisense or any other productivity-boosting features of a good IDE</li>
<li>Invoking scripted methods is always going to be significantly slower than compiled code</li>
<li>Weak built-in libraries and language features compared to C#/.NET. Also, it's much easier to write run-time safe code in a compiled language.</li>
<li>The engine is already in C#, so having no cross-language boundaries is an advantage.</li>
</ul>
<div>
One reason I wanted a scripting language in the first place is so the game could be ported by having the majority of content in Lua scripts with a slimmer engine that could easily be converted to C++ if needed. However, I can use Mono in the future instead if I really want to.</div>
</div>
<div>
<br /></div>
<div>
So, with this in mind, I've decided to go C# all the way. Because all game logic is in a separate assembly with no dependency on the engine, it can be considered a 'plugin'. It is bound at run-time rather than compile time. The below picture demonstrates how my assembly structure is set up:</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvAfWyDTNljd7Iu6oEKQz6KHc6Vp81OZX7jK_Zbfqw7ctr7ebI4v7sfsZsWHHgEgi7l6-3nLChG58nQXoKdqqRGbRaAikJmWdjJn-2xUDEZoZpe6bFYPLnQHDAXNi5XV5kXupiNeJTVjs/s1600/ss47.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="350" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvAfWyDTNljd7Iu6oEKQz6KHc6Vp81OZX7jK_Zbfqw7ctr7ebI4v7sfsZsWHHgEgi7l6-3nLChG58nQXoKdqqRGbRaAikJmWdjJn-2xUDEZoZpe6bFYPLnQHDAXNi5XV5kXupiNeJTVjs/s400/ss47.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
So, things like 'player' and 'spike' (currently the only two complex behaviors I have) live in the Implementation assembly. The game engine (and thus the editor) dynamically load this assembly at run-time and use reflection to instantiate 'Behavior' objects (or, in the editor's case, let the user assign behaviors to an entity. I haven't actually done that part yet.)</div>
<div>
<br /></div>
<div>
So, yeah, the result of all this stuff is that I'm not using Lua anymore. I may or may not use it in the future for <b>simple </b>behaviors (i.e. this switch opens that door, etc), but all complex behaviors will be in C#. And with the way I've structured my project, the engine can be used by anyone who wants to build their own game--they simple need to implement behaviors in their own assembly and modify a text file which tells the engine what assembly to dynamically load.</div>
<div>
<br /></div>
<div>
So, this conversion took the majority of my time this week, but I still had a little time to have some fun. </div>
<div>
<br /><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifcBFWzSYbo_6k_dm-03ywUmj3Xmmi9T_cevjXHrHeXhpG-hNWn9w3XUhxR_UcRqQv03jKFdrqwP3sN5WPpl5PRUxxuwkWkb-mirv5daC_-ftlTuLcb78Xx_QvBSmzP-TY9EjruU3f0_U/s1600/ss48.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifcBFWzSYbo_6k_dm-03ywUmj3Xmmi9T_cevjXHrHeXhpG-hNWn9w3XUhxR_UcRqQv03jKFdrqwP3sN5WPpl5PRUxxuwkWkb-mirv5daC_-ftlTuLcb78Xx_QvBSmzP-TY9EjruU3f0_U/s400/ss48.png" width="400" /></a></div>
</div>
<div>
<br /></div>
<div>
Here's some things I did for fun after converting everything to C#:</div>
<div>
<ul>
<li>Enhance the trigger infrastructure to take arbitrary trigger arguments. For example, the 'DamageEnemy' trigger might take 'damage amount' and 'damage type' as arguments, and also a 'damage direction' that an enemy that receives 'knockback' might use.</li>
<li>Made it so the spike enemy can 'damage' the player. There's no damage meter yet (maybe next update?), but there's a cool knockback-and-temporary-invincibility effect very similar to how 'A Link to the Past' handles damage. See video below for a demo!</li>
<li>The player can slash at the spike enemies to similarly knock them back. Also shown in the video.</li>
</ul>
<div>
Okay, here's a video of all that stuff in action:</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/vJ4rsD0SQqw?feature=player_embedded' frameborder='0'></iframe></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
One thing worth mentioning is how the the game handles the enemy collision with the player's sword. Here's the source code for that part:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbRWQ7KYePQuNT4aya9uzt-aek4Zvd94OyMh9ECYliTmuDmmr-fZxd7UVHwwxSAUel3J0epja3sXIUtsfzrrHWOHGcYSEAc1CvFQm9PwAWDEFAWcqX7WovRF2lw-taeu34rosEtCZLno8/s1600/ss49.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="345" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbRWQ7KYePQuNT4aya9uzt-aek4Zvd94OyMh9ECYliTmuDmmr-fZxd7UVHwwxSAUel3J0epja3sXIUtsfzrrHWOHGcYSEAc1CvFQm9PwAWDEFAWcqX7WovRF2lw-taeu34rosEtCZLno8/s640/ss49.png" width="640" /></a></div>
<div>
<br /></div>
<div>
Here is a short video showing how it works. Note that for the video I've dramatically slowed down time, zoomed in, and turned the opacity to 0.7 for the 'sword' entity instead of 0. The rotating white block is actually what's doing all of the work here!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/2QHfgFoEoaI?feature=player_embedded' frameborder='0'></iframe></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
And, if you're interested, a brief translation of the code to English:</div>
<div>
<ol>
<li>Translate the player's 'facing' variable (left, right, up, down) into an angle.</li>
<li>Create a 'sword node' at the player's position. This is because I don't have support for rotation 'around' an arbitrary point, so to simulate that I use entity parenting--create a node, attach the thing you want to rotate to it as a child (and position it relative to the node), and then rotate the node.</li>
<li>The line 'swordNode.Control(...)' sets up rotation from sourceRotation to targetRotation. The arc angle (it's declared outside of the shown code) is about 33 degrees (pi * 3 / 16). </li>
<li>Create an actual 'sword' and append it to the node. Note that the sword is an abstract thing and not visible--the graphic for the player has the sword 'built-in'.</li>
<li>Position it 30 units ahead of the player and give it a certain size.</li>
<li>Attach a collision event to the invisible 'sword' object. The callback (an anonymous method here) simply invokes a trigger on the target entity (it uses the player's position to calculate the knockback direction). The collision event's current target is 'spike', but in the future we'd make it 'enemy' or even 'takesSwordDamage', and make all things that can be hurt with a sword handle that trigger.</li>
<li>I attach an 'update' function to the sword which generates some particles as it swings.</li>
<li>I set a texture for debugging purposes, but set the opacity to 0, so you can't see it.</li>
<li>Finally, I run the animation for the player and when it's over set its state back to 'standard' (the code above actually runs in the initializer for a 'swording' state).</li>
</ol>
</div>
<div>
Okay, that's all for this update. I hope it was interesting. Next I'll be adding a health meter to the player and to enemies, or something of that nature.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Erichttp://www.blogger.com/profile/17829154021421876095noreply@blogger.com0