tag:blogger.com,1999:blog-238091152024-03-18T19:46:35.904-07:00Greg LiebermanGames, projects, and other distractionsGreg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.comBlogger29125tag:blogger.com,1999:blog-23809115.post-12883791666884553182021-03-03T00:56:00.004-08:002021-03-03T00:58:43.529-08:00My Code Needed a Comment to Compile<p><span style="background-color: black;"><span><span style="font-family: inherit;"> </span></span><span style="font-family: inherit; font-size: 13px;">When I was learning python, I added a utf-8 string literal to the source code as follows:</span></span></p><p class="_1qeIAgB0cPwnLhDF9XSiJM" style="border: 0px; font-size: 14px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0.8em 0px 0.25em; vertical-align: baseline;"><span><span style="background-color: black; font-family: inherit;"><code class="_34q3PgLsx9zIU5BiSOjFoM" style="border: 0px; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 20px; margin: 0px 2px; max-width: 100%; overflow: auto; padding: 0px; vertical-align: baseline;"># replace invalid ’ character with '</code><br /><code class="_34q3PgLsx9zIU5BiSOjFoM" style="border: 0px; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 20px; margin: 0px 2px; max-width: 100%; overflow: auto; padding: 0px; vertical-align: baseline;">inputFileContents = inputFileContents.replace('’', "'")</code></span></span></p><p class="_1qeIAgB0cPwnLhDF9XSiJM" style="border: 0px; font-size: 14px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0.8em 0px 0.25em; vertical-align: baseline;"><span><span style="background-color: black; font-family: inherit;">Which caused this error:</span></span></p><p class="_1qeIAgB0cPwnLhDF9XSiJM" style="border: 0px; font-size: 14px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0.8em 0px 0.25em; vertical-align: baseline;"><code class="_34q3PgLsx9zIU5BiSOjFoM" style="border: 0px; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 20px; margin: 0px 2px; max-width: 100%; overflow: auto; padding: 0px; vertical-align: baseline;"><span style="background-color: black; font-family: inherit;">SyntaxError: Non-ASCII character '\xe2' in file gcnlsync.py on line 85, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details</span></code></p><p class="_1qeIAgB0cPwnLhDF9XSiJM" style="border: 0px; font-size: 14px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0.8em 0px 0.25em; vertical-align: baseline;"><span><span style="background-color: black; font-family: inherit;">My python code would not run until I <a class="_3t5uN8xUmg0TOwRCOGQEcU" href="https://www.python.org/dev/peps/pep-0263/" rel="noopener nofollow ugc" style="border: 0px; font-size: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;" target="_blank">added a comment</a> to the file that declared utf-8 encoding. This is literally the top 2 lines of my file:</span></span></p><p class="_1qeIAgB0cPwnLhDF9XSiJM" style="border: 0px; font-size: 14px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0.8em 0px 0.25em; vertical-align: baseline;"><span><span style="background-color: black; font-family: inherit;"><code class="_34q3PgLsx9zIU5BiSOjFoM" style="border: 0px; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 20px; margin: 0px 2px; max-width: 100%; overflow: auto; padding: 0px; vertical-align: baseline;">#!/usr/bin/python</code><br /><code class="_34q3PgLsx9zIU5BiSOjFoM" style="border: 0px; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: 20px; margin: 0px 2px; max-width: 100%; overflow: auto; padding: 0px; vertical-align: baseline;"># This Python file uses the following encoding: utf-8</code></span></span></p><p class="_1qeIAgB0cPwnLhDF9XSiJM" style="border: 0px; font-size: 14px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0.8em 0px 0px; vertical-align: baseline;"><span><span style="background-color: black; font-family: inherit;">After adding the comment, it ran perfectly! 😳</span></span></p>Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-42439978661028066652016-11-28T23:32:00.000-08:002016-11-28T23:45:14.364-08:00Raspberry Pi Apartment HunterMany apartment complexes use sophisticated algorithms to change lease prices on a daily basis. If they can use an algorithm to maximize value, I can too!<br />
<div>
<br /></div>
<div>
In this post, I will walk through the steps I took to grab data from an apartment leasing website, monitor changes, and send me email alerts.<br />
<br />
<br /></div>
<h2>
Grabbing the Data</h2>
<div>
In this example we will take a dive into a <a href="https://www.avaloncommunities.com/california/glendale-apartments/avalon-glendale">Leasing Website in Glendale</a></div>
<div>
<br /></div>
<div>
A click on "Apartments + Pricing" will reveal a page that looks like this:</div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW-n8lMkb2YEuCWYh3Z1GOTHiR1yZFcawTYipS5_WujJmepALzpPzn1YoyTqsJdPL4oqjfi0mBJq6v1Bt4_23111EW9pQSkAt30NAkmbe5M7WN3ITaZyV8eoHQbqv3lNS-8Pxh/s1600/Screen+Shot+2016-09-12+at+11.00.56+PM.png" imageanchor="1"><img border="0" height="275" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW-n8lMkb2YEuCWYh3Z1GOTHiR1yZFcawTYipS5_WujJmepALzpPzn1YoyTqsJdPL4oqjfi0mBJq6v1Bt4_23111EW9pQSkAt30NAkmbe5M7WN3ITaZyV8eoHQbqv3lNS-8Pxh/s640/Screen+Shot+2016-09-12+at+11.00.56+PM.png" width="640" /></a></div>
<div>
<br /></div>
<div>
The web page is retrieving the apartment data from a remote server. Let's see if we can find it.</div>
<div>
<br /></div>
<div>
Using the Google Chrome web browser, select "View -> Developer -> Developer Tools", and refresh the web page.</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggPK69x7LdhmYaBTE7GBaGWErYH7zoRh1RpWiYIPAb4UOUc7-UIoiwazgF69eoWMRfucniC622GMTjuFhkv9qWQhMXrbqv8x0A6JcGXj4NafPR6uGNevAE6R1-mxw7AGMwAOo6/s1600/Screen+Shot+2016-09-12+at+11.06.14+PM.png" imageanchor="1"><img border="0" height="334" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggPK69x7LdhmYaBTE7GBaGWErYH7zoRh1RpWiYIPAb4UOUc7-UIoiwazgF69eoWMRfucniC622GMTjuFhkv9qWQhMXrbqv8x0A6JcGXj4NafPR6uGNevAE6R1-mxw7AGMwAOo6/s640/Screen+Shot+2016-09-12+at+11.06.14+PM.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
In our Developer Console, we see dozens of javascript executions and connections to remote urls. One of the urls is called "ApartmentSearch". It contains all the beautiful apartment data we want. </div>
<div>
<br /></div>
<div>
<a href="https://api.avalonbay.com/json/reply/ApartmentSearch?communityCode=CA068&min=2200&max=3400&_=1480230523132">https://api.avalonbay.com/json/reply/ApartmentSearch?communityCode=CA068&min=2200&max=3400&_=1480230523132</a></div>
<div>
<br /></div>
<div>
Copy/paste the url into a new browser tab, and you'll find a handy, if messy, wall of JSON text.</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOh8eby-Sdzs5bO-Qku_hi5mLpabYS7ATD2JgdNA8eWf06EKmyp3DdfVUbhFimh31difMJ7bzoInxT5L1Rj4Q1NIWsuTmVlbYelvn4VVWYgZUqavDZUgvVpaLxKo-9qBrz9ofq/s1600/Screen+Shot+2016-09-12+at+11.06.54+PM.png" imageanchor="1"><img border="0" height="352" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOh8eby-Sdzs5bO-Qku_hi5mLpabYS7ATD2JgdNA8eWf06EKmyp3DdfVUbhFimh31difMJ7bzoInxT5L1Rj4Q1NIWsuTmVlbYelvn4VVWYgZUqavDZUgvVpaLxKo-9qBrz9ofq/s640/Screen+Shot+2016-09-12+at+11.06.54+PM.png" width="640" /></a></div>
<div>
<br /></div>
<div>
Copy all the text. Let's visit <a href="http://jsonlint.com/">jsonlint.com</a> and pretty it up:</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivkbG2LPL7sG1dtR5Nlrix6L5FOeddnIIkkABBFfXEAEge0TQYIuNYHRaDRCM3gdNPmTRW4bQEyTwza3DCF0CfU439RhNMYYQftobOFNrckaUrBuWsyJNrEBCMc-MRTBczscSK/s1600/Screen+Shot+2016-09-12+at+11.07.20+PM.png" imageanchor="1"><img border="0" height="472" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivkbG2LPL7sG1dtR5Nlrix6L5FOeddnIIkkABBFfXEAEge0TQYIuNYHRaDRCM3gdNPmTRW4bQEyTwza3DCF0CfU439RhNMYYQftobOFNrckaUrBuWsyJNrEBCMc-MRTBczscSK/s640/Screen+Shot+2016-09-12+at+11.07.20+PM.png" width="640" /></a></div>
<div>
<br /></div>
<div>
Fantastic! Scrolling through this data, we can find every apartment and its current lease price.</div>
<div>
<br /></div>
<div>
<br />
<br />
<br /></div>
<h2>
Monitoring Data with a Raspberry Pi</h2>
<div>
The website gives us a JSON object, which is very easy to read and manipulate in JavaScript. I wrote a server-side JavaScript script, "apartment.js", that parses the JSON data, and writes to a CSV file. Later, we use the CSV file to make pretty graphs in Microsoft Excel.</div>
<div>
<br /></div>
<div>
Here is a screenshot of the code parsing the JSON object:</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhetuyllVd-JR3hAkf8YSbOI-sEEN71tqAZUGoMONhD35QTo-_b_RTCu02SDiSEwdtc7IqXEeuE0CRIg8mroxyP2IfCfM2V9Kc8DJjrg4vkH8Btz_LAbv-bBdK-z4fMFh0VMdU6/s1600/Screen+Shot+2016-09-12+at+11.08.15+PM.png" imageanchor="1"><img border="0" height="446" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhetuyllVd-JR3hAkf8YSbOI-sEEN71tqAZUGoMONhD35QTo-_b_RTCu02SDiSEwdtc7IqXEeuE0CRIg8mroxyP2IfCfM2V9Kc8DJjrg4vkH8Btz_LAbv-bBdK-z4fMFh0VMdU6/s640/Screen+Shot+2016-09-12+at+11.08.15+PM.png" width="640" /></a></div>
<div>
<br /></div>
<div>
When the data is saved to a CSV file, it looks like this:</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiK6wKq0iP3PW6xbw0VrrjAot5OEKfmYCdIXnWbY-3Hr2b_XsKMuQV4P0CeMFDAYJl-gNclfVBSD3obu3_AFL7WpseW30dLPArB6n1ar5HiNj9tU8zQh7yV_xv7X7OXVVcupuof/s1600/Screen+Shot+2016-09-12+at+11.09.23+PM.png" imageanchor="1"><img border="0" height="364" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiK6wKq0iP3PW6xbw0VrrjAot5OEKfmYCdIXnWbY-3Hr2b_XsKMuQV4P0CeMFDAYJl-gNclfVBSD3obu3_AFL7WpseW30dLPArB6n1ar5HiNj9tU8zQh7yV_xv7X7OXVVcupuof/s640/Screen+Shot+2016-09-12+at+11.09.23+PM.png" width="640" /></a></div>
<div>
<br /></div>
<div>
I used a Raspberry Pi computer to run my "apartment.js" script every 6 hours. Each time the script ran, it would parse the JSON object, and add the current apartment prices to the CSV file. Server-side Javascript is possible thanks to the <a href="https://nodejs.org/en/">NodeJS</a> project. <a href="https://www.raspberrypi.org/">Raspberry Pi</a> is an inexpensive computer that is popular for open-source projects. What I like most about a Raspberry Pi is that I can leave it on all the time without worrying about an expensive energy bill.</div>
<div>
<br /></div>
<h3>
Running a script every 6 hours with crontab</h3>
<div>
Here I log into my Raspberry Pi and execute "crontab -e". This can be done on any Unix-like machine such as Mac OS or Linux<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXOKJGHMMNHe6knUMrF7y1MSOhnucvxf-yMC2q6MmwqIkSk0evcRVbh7T6nB78XCr5gKMem5cQLV8-vvgGFtrfHhOlBkJ8QsF8HuLYRux7UDyFzWfmNBEbHAcZ173mlwFKFCZd/s1600/Screenshot+at+Nov+28+01-28-44.png" imageanchor="1"><img border="0" height="194" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXOKJGHMMNHe6knUMrF7y1MSOhnucvxf-yMC2q6MmwqIkSk0evcRVbh7T6nB78XCr5gKMem5cQLV8-vvgGFtrfHhOlBkJ8QsF8HuLYRux7UDyFzWfmNBEbHAcZ173mlwFKFCZd/s640/Screenshot+at+Nov+28+01-28-44.png" width="640" /></a></div>
<div>
<br />
Inside cron, the bottom line runs the "apartment.js" script every 6 hours.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZMYKdeVlziIprAsl-_UsMf7es7qRPpBIMpCm0BW_dnMKnvWK2b1G2GgR8eyqzhSrwWRlgI197i_ybVKfQAKETK2iaUv_dnEjrBhyfxGjuoxoS9GhbAnwOMnox2exrNNaLgXio/s1600/Screenshot+at+Nov+28+01-26-01.png" imageanchor="1"><img border="0" height="478" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZMYKdeVlziIprAsl-_UsMf7es7qRPpBIMpCm0BW_dnMKnvWK2b1G2GgR8eyqzhSrwWRlgI197i_ybVKfQAKETK2iaUv_dnEjrBhyfxGjuoxoS9GhbAnwOMnox2exrNNaLgXio/s640/Screenshot+at+Nov+28+01-26-01.png" width="640" /></a><br />
<br />
<br />
<h2>
Pretty Graphs</h2>
What did we learn?<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNWvQkFQiWuAtKRjn_4yPyDuHikZVMITRyQU1WxahfUgJi9O6yA5vR3SpBpU2Hd3cvMcODWkmQ6VIce3C8CP0joffmasPK2hPirGO7-yBvxPA29IunFNWjWg7sG4KECc8cy7kl/s1600/Screenshot+at+Nov+28+01-57-20.png" imageanchor="1"><img border="0" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNWvQkFQiWuAtKRjn_4yPyDuHikZVMITRyQU1WxahfUgJi9O6yA5vR3SpBpU2Hd3cvMcODWkmQ6VIce3C8CP0joffmasPK2hPirGO7-yBvxPA29IunFNWjWg7sG4KECc8cy7kl/s400/Screenshot+at+Nov+28+01-57-20.png" width="400" /></a><br />
<br />
Between September 13th and October 7th, apartment 106 bounced around in price. Eventually, it slid to a sweet $2150 before being sold. Whoever claimed it got a great deal.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1u8whw3oGl0N9wdKS-siI5dfTU3NLPlCdxjHrBZITdO9K0KjtKV71KSeaHVpjuvOypMFM727KfzD46PqCr8DhcCJ-nbDneNB1oofhI2UcQuYwKXzWHMxvcTCHPvQSCg_fgJ_O/s1600/Screenshot+at+Nov+28+02-03-38.png" imageanchor="1"><img border="0" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1u8whw3oGl0N9wdKS-siI5dfTU3NLPlCdxjHrBZITdO9K0KjtKV71KSeaHVpjuvOypMFM727KfzD46PqCr8DhcCJ-nbDneNB1oofhI2UcQuYwKXzWHMxvcTCHPvQSCg_fgJ_O/s400/Screenshot+at+Nov+28+02-03-38.png" width="400" /></a><br />
<br />
Between September 13th and October 16th, apartment 109 slid to an even cheaper price at $2070. However, after 106 sold, it quickly shot up in price and stubbornly stayed there. 109 was sold on October 16th for $2200. Whoever bought it missed the optimal deal.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9SvkQHKb-RV3cN3iv0rUwfDL0iguYI5nWInqXfyzIuMOx21u8Xp-MhX6gPE0DnmJT94_YoLL_TPABvYn_FXEbsuyt3U9PmRMDSQWw4Zremrx7lMBzmjeI_Fnu3C9vyKIcaxwq/s1600/Screenshot+at+Nov+28+02-10-46.png" imageanchor="1"><img border="0" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9SvkQHKb-RV3cN3iv0rUwfDL0iguYI5nWInqXfyzIuMOx21u8Xp-MhX6gPE0DnmJT94_YoLL_TPABvYn_FXEbsuyt3U9PmRMDSQWw4Zremrx7lMBzmjeI_Fnu3C9vyKIcaxwq/s400/Screenshot+at+Nov+28+02-10-46.png" width="400" /></a><br />
<br />
Apartment 117 appeared on November 4th, and quickly shot up in price. It's been more than 20 days and no one has bought it...<br />
<br />
Later, I will share more graphs if I discover any interesting trends.<br />
<br />
<br /></div>
<h2>
Email Alerts</h2>
<div>
As the Raspberry Pi collected data, I had it send me emails when something interesting happened:</div>
<div>
<ol>
<li>When any apartment reached its cheapest price ever</li>
<li>When any apartment became vacant or sold</li>
</ol>
<div>
This way, I didn't need to refresh the leasing website like a crazy person. </div>
</div>
<div>
<br /></div>
<div>
Side note:</div>
<blockquote class="tr_bq">
I implemented this algorithm for myself, so I took the lazy route and stored data in a text file for a single user. For a more scalable solution, I would recommend a <a href="https://www.mongodb.com/">MongoDB</a> database. I chose to skip installing MongoDB at the time because the official MongoDB binaries did not support my Raspberry Pi.</blockquote>
<h3>
Cheapest Price Ever</h3>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpVTRv-GCN9yZy_Mqh-peB4XiA-y9Bya1dYvfRFEAX0-AWvyOF2UjzpuQwO3Z8OsPZdzZwlzp3NmjsURpoD8ezsGcMeLaCZNdSypWID5EfnFx-JPsS62JIi72xUZsWzfnMYOPl/s1600/Screenshot+at+Nov+27+02-32-36.png" imageanchor="1"><img border="0" height="274" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpVTRv-GCN9yZy_Mqh-peB4XiA-y9Bya1dYvfRFEAX0-AWvyOF2UjzpuQwO3Z8OsPZdzZwlzp3NmjsURpoD8ezsGcMeLaCZNdSypWID5EfnFx-JPsS62JIi72xUZsWzfnMYOPl/s640/Screenshot+at+Nov+27+02-32-36.png" width="640" /></a></div>
<div>
<br /></div>
<div>
Prices dropped in September and October as vacancies opened up:</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbDzFv6FuaN48KpDPnpqIgkS0f6um0xVRZYRXXsGzg_Ywwdkx84KP80hQzxf39MIBNy6XJXFA8pP9Q5BYCBQlBUMOn3-i0cosOK9z_tg6LGB6UO0Pn9gUytJ1fqPxxt0s-Ww2X/s1600/Screenshot+at+Nov+27+02-06-11.png" imageanchor="1"><img border="0" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbDzFv6FuaN48KpDPnpqIgkS0f6um0xVRZYRXXsGzg_Ywwdkx84KP80hQzxf39MIBNy6XJXFA8pP9Q5BYCBQlBUMOn3-i0cosOK9z_tg6LGB6UO0Pn9gUytJ1fqPxxt0s-Ww2X/s640/Screenshot+at+Nov+27+02-06-11.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPzxjjCVZenU1J5fF5G1In5xG5PH-Ft5hAy2pt702RT5dYv_JGLh4ZOFRlJ-0PhiLtIAs1VBu9yzVHIGwoeNXqh4LpWABzge2Qv4Q0Zyh6Q3ms5dDwsA9Cygzox2FXzJ15uKcK/s1600/Screenshot+at+Nov+27+01-59-02.png" imageanchor="1"><img border="0" height="164" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPzxjjCVZenU1J5fF5G1In5xG5PH-Ft5hAy2pt702RT5dYv_JGLh4ZOFRlJ-0PhiLtIAs1VBu9yzVHIGwoeNXqh4LpWABzge2Qv4Q0Zyh6Q3ms5dDwsA9Cygzox2FXzJ15uKcK/s400/Screenshot+at+Nov+27+01-59-02.png" width="400" /></a></div>
<div>
<br /></div>
<div>
Eventually, a one-bedroom apartment bottomed out at $2070</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk0K9K7lT2YC5Q6wzKgz4EQY-ldv3uaDuTrL1FEx2f0r5jEN6tw_cjAZeVnn06yzqGUA8wWUo2AweAIJ07sXxaHumvUiRYOQB_sMrv1vTO0Xin-Ez9BGRuR226AiCDoI_BI2-T/s1600/Screenshot+at+Nov+27+01-59-30.png" imageanchor="1"><img border="0" height="146" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk0K9K7lT2YC5Q6wzKgz4EQY-ldv3uaDuTrL1FEx2f0r5jEN6tw_cjAZeVnn06yzqGUA8wWUo2AweAIJ07sXxaHumvUiRYOQB_sMrv1vTO0Xin-Ez9BGRuR226AiCDoI_BI2-T/s320/Screenshot+at+Nov+27+01-59-30.png" width="320" /></a></div>
<div>
<br /></div>
<div>
Vacancies were sold and prices have climbed ever since.</div>
<div>
<br /></div>
<h3>
Apartment Vacancy Changes</h3>
<div>
Starting on October 16th, I programmed the Pi to email me about vacancy changes</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjE-zKFc0FeIs3FGFWva9JzX1NfqfTmJT5RQ9EVpg_2gxY5Yw9OIe72DGvZRrMGulghGvLFv0UKHQBH9jk60v8OB16I_fCwVpOhq7xLMgaOV58ODQiYbKnP-zEfWi2K8zkmwTEr/s1600/Screenshot+at+Nov+27+02-32-54.png" imageanchor="1"><img border="0" height="326" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjE-zKFc0FeIs3FGFWva9JzX1NfqfTmJT5RQ9EVpg_2gxY5Yw9OIe72DGvZRrMGulghGvLFv0UKHQBH9jk60v8OB16I_fCwVpOhq7xLMgaOV58ODQiYbKnP-zEfWi2K8zkmwTEr/s640/Screenshot+at+Nov+27+02-32-54.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<div>
My email archives tell me a lot about how often vacancies were added or sold:</div>
</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGjkVQA7kJ-wiF2GO58ec4aYmgHTj8p2jrOFGXNWaWkvOskTgZT44HaPMol1xc9DSXrhHH7qKzMfY07vAU3knCpkBbJ9gifu-8jrg9VBGcSrafTJUAergSALP0I-qlyo0W6enJ/s1600/Screenshot+at+Nov+27+02-08-57.png" imageanchor="1"><img border="0" height="271" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGjkVQA7kJ-wiF2GO58ec4aYmgHTj8p2jrOFGXNWaWkvOskTgZT44HaPMol1xc9DSXrhHH7qKzMfY07vAU3knCpkBbJ9gifu-8jrg9VBGcSrafTJUAergSALP0I-qlyo0W6enJ/s640/Screenshot+at+Nov+27+02-08-57.png" width="640" /></a></div>
<div>
<br /></div>
<div>
Notice that vacancies changed every 5-10 days until the middle of November. Since then, vacancies haven't changed for more than 20 days.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGnm1k1oCIbKtozfqGHFGw86w6PSO4jgthG3iRUJGq5puNEofBWPFH2bAb21ULvg4inFWLweyXjAvPsALfhtRYtS72Jata8DdFzmtTTIqZZV1DxmjzzJrd9zH14arKFG81DXMP/s1600/Screen+Shot+2016-11-27+at+2.10.25+AM.png" imageanchor="1"><img border="0" height="224" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGnm1k1oCIbKtozfqGHFGw86w6PSO4jgthG3iRUJGq5puNEofBWPFH2bAb21ULvg4inFWLweyXjAvPsALfhtRYtS72Jata8DdFzmtTTIqZZV1DxmjzzJrd9zH14arKFG81DXMP/s640/Screen+Shot+2016-11-27+at+2.10.25+AM.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7Ht8npy8SAr79qko8g20ePYbVceQJfYiDAN6aq84zKs_Xlwt27MpMXvLV7l192dOurFI0-hAgjumx98JyjiGGMF5qKvuWYW1ck-nZeViJVWzyRjaknyzZmwOJ1dcoFXsNDP94/s1600/Screenshot+at+Nov+27+02-22-54.png" imageanchor="1"><img border="0" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7Ht8npy8SAr79qko8g20ePYbVceQJfYiDAN6aq84zKs_Xlwt27MpMXvLV7l192dOurFI0-hAgjumx98JyjiGGMF5qKvuWYW1ck-nZeViJVWzyRjaknyzZmwOJ1dcoFXsNDP94/s640/Screenshot+at+Nov+27+02-22-54.png" width="640" /></a></div>
<div>
<br /></div>
<div>
New apartments usually would popup with with much-higher-than-average prices. 😅</div>
<div>
<br /></div>
<h2>
Source Code</h2>
<div>
I uploaded the source code onto GitHub!</div>
<div>
<a href="https://github.com/KWarp/Apartment-Hunter">https://github.com/KWarp/Apartment-Hunter</a></div>
<div>
<br />
<br />
<h2>
Conclusion</h2>
My Apartment Hunting algorithm confirmed the obvious. When lots of apartments are vacant for a long time, their prices slowly drop until they are sold. After one sells, the remaining apartments spike in price for a while.<br />
<br />
The email alerts were certainly handy. I didn't need to worry about refreshing the web page every day for the best deal. With my Raspberry Pi collecting data directly, the apartment company could not track any web browsing data about me. That in itself was its own reward.<br />
<br /></div>
<div>
<br /></div>
Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com1tag:blogger.com,1999:blog-23809115.post-35330344175629307342016-08-22T23:55:00.002-07:002016-08-22T23:55:39.089-07:00Video Game Prototyping<div class="_1dwg _1w_m" style="font-family: inherit; padding: 12px 12px 0px;">
<div class="_5pbx userContent" data-ft="{"tn":"K"}" id="js_11" style="font-family: inherit; font-size: 14px; line-height: 1.38; overflow: hidden;">
<div style="font-family: inherit; margin-bottom: 6px;">
Video Game Prototyping is an emotional roller coaster. Two months ago, I started hammering at a totally amazing game idea. Every day was a coding frenzy. I couldn’t wait to get the game in people’s hands.</div>
<div style="font-family: inherit; margin-bottom: 6px; margin-top: 6px;">
After a week, the first playable was ready. Players were excited by the gameplay, but wildly confused by the touch screen controls. I took a step back, and simplified the game controls from 8 buttons to 3 buttons. As a result, the game lost some of its strategic depth.</div>
<div style="font-family: inherit; margin-bottom: 6px; margin-top: 6px;">
Another playtest took place. Players found the game easier to play, but also less interesting. Feeling humbled, but not discouraged, I set out to find the new fun factor the game needed. I spent days churning out one game mechanic after another. I felt completely in my element, putting all of my skills to the test.</div>
<div style="font-family: inherit; margin-bottom: 6px; margin-top: 6px;">
As the days went by, none of the mechanics stuck. I felt this sinking feeling that maybe I can’t figure this one out. Each day became more difficult, each mechanic less fun, and after 8 days I ran out of ideas. My confidence hit an all-time low. Why was I even wasting my time on this?</div>
<div style="font-family: inherit; margin-bottom: 6px; margin-top: 6px;">
The next day, an innocent thought popped into my head. The Bullet mechanic was fun, but lacked strategy. The Bomb mechanic was strategic, but too slow. What if… the bullets were also bombs? And a skillful player can strategically detonate them?</div>
<div style="font-family: inherit; margin-bottom: 6px; margin-top: 6px;">
My confidence started climbing. This tiny layer of strategy enhanced every aspect of the game. Play time jumped from 2 minutes to 10 minutes. Laughing and trash talk ensued. The game was back on track, and even better than before.</div>
<div style="display: inline; font-family: inherit; margin-top: 6px;">
This is an ongoing project. My mind is buzzing with ideas. Hopefully I can share it with you all soon!</div>
<div class="_5wpt" style="border-left: 2px solid rgb(220, 222, 227); font-family: inherit; padding-left: 12px;">
</div>
</div>
<div class="_3x-2" style="font-family: inherit;">
<div data-ft="{"tn":"H"}" style="font-family: inherit;">
</div>
</div>
</div>
<div style="font-family: inherit;">
<form action="https://www.facebook.com/ajax/ufi/modify.php" class="commentable_item" data-ft="{"tn":"]"}" id="u_jsonp_2_f" method="post" rel="async" style="margin: 0px; padding: 0px;">
<div class="_sa_ _5vsi _ca7 _192z" style="color: #90949c; font-family: inherit; margin-top: 12px; padding-bottom: 4px; position: relative;">
<div class="_37uu" style="font-family: inherit;">
<div data-reactroot="" style="font-family: inherit;">
<div class="_3399 _a7s clearfix" style="border-top: 1px solid rgb(229, 229, 229); clear: both; font-family: inherit; margin: 0px 12px; padding-top: 4px; zoom: 1;">
<div class="_524d" style="font-family: inherit;">
</div>
</div>
</div>
</div>
</div>
</form>
</div>
Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-67098536043571854742015-07-19T21:58:00.000-07:002015-07-29T11:47:53.770-07:00Unity: Rotate a 3D ball using 2D Physics<a href="https://unity3d.com/" target="_blank">Unity</a> is an awesome game engine with great 2D and 3D features. While working on a 2D game world with 3D game art, I ran into an unexpected challenge with rolling 3D spheres. Let's frame the problem in the context of a 2D soccer game with a top-down view.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjpsmZczkOhAuSx8LtDXkiCmduMo78wBpPYnzkIoY6xmoEsnpQb3PeYAJ_UxrcjfJnpI98cq6_RL6capWc4NaKQUKDs_0LptCJxPuAhWCatMsTtQvEaCrijG-7yqtVGtDmFPRB/s1600/football-pitch_0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjpsmZczkOhAuSx8LtDXkiCmduMo78wBpPYnzkIoY6xmoEsnpQb3PeYAJ_UxrcjfJnpI98cq6_RL6capWc4NaKQUKDs_0LptCJxPuAhWCatMsTtQvEaCrijG-7yqtVGtDmFPRB/s320/football-pitch_0.png" width="320" /></a></div>
<br />
TL;DR<br />
<a href="http://www.gfycat.com/ImperturbableQuickBuzzard" target="_blank">Before (animated gif)</a><br />
<a href="http://www.gfycat.com/ShorttermFortunateFanworms" target="_blank">After (animated gif)</a><br />
<a href="https://github.com/KWarp/BallRoll">GitHub Project</a><br />
<br />
<a name='more'></a><br />
<br />
<h2>
Soccer Games</h2>
When building a 2D soccer game, a common problem is figuring out how to animate a rolling soccer ball. Soccer balls have 360 degrees of movement, so the conventional approach of animated sprite sheets does not look particularly realistic.<br />
<br />
<h2>
Sprite Sheets </h2>
A google search of "<a href="https://www.google.com/webhp#q=soccer%20ball%20sprite%20sheet" target="_blank">soccer ball sprite sheet</a>" is littered with incomplete solutions.<br />
<br />
Often, game developers just don't animate the soccer ball at all:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/Jhv_dV5LWGA/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/Jhv_dV5LWGA?feature=player_embedded" width="320"></iframe></div>
<br />
<br />
Other times, the soccer ball animation is dramatically simplified:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/vvr5rutXT8A/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/vvr5rutXT8A?feature=player_embedded" width="320"></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Notice that the ball only rotates in 2 directions: clockwise or counter-clockwise. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h2 style="clear: both; text-align: left;">
3D Soccer Ball</h2>
<div class="separator" style="clear: both; text-align: left;">
A 3D sphere made in Unity animates perfectly, because its RigidBody allows it to automatically roll around in 3D space. </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/AVvXsEisf1B_Y2sNy5-NJyqraBJIh3A10kcSlAcmXRBOffLnURT8O4d-5bqp-zsS7xGcQy2I1nO03aHucV5Rkhwe6EHQA_v7q0U8gOgBuw0OAsMjRWlSMzCj7Chr_2iFCbdqwwjedKyL/s1600/playerball3dphysics.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="264" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisf1B_Y2sNy5-NJyqraBJIh3A10kcSlAcmXRBOffLnURT8O4d-5bqp-zsS7xGcQy2I1nO03aHucV5Rkhwe6EHQA_v7q0U8gOgBuw0OAsMjRWlSMzCj7Chr_2iFCbdqwwjedKyL/s320/playerball3dphysics.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: left;">
<a href="http://www.gfycat.com/IncomparableJitteryHound" target="_blank">Rigidbody ball physics (animated gif)</a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Unfortunately, using 3D physics for the ball means that your entire Unity game must use 3D physics. There are several reasons you may not want a 2D-looking game to have 3D game physics:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ol>
<li>Most collisions of the soccer ball can send it flying on the Z-axis. The ball could look like it is in the right place for a soccer player to hit the ball, but it could completely miss because the ball is 20 units above the player's head. </li>
<li>A dogpile of soccer players can stack in the Z-direction, messing up the look and feel of the game. </li>
<li>3D physics feels very different from 2D physics</li>
<li>3D physics is just more complicated</li>
</ol>
<div class="separator" style="clear: both; text-align: left;">
Assuming you are dead-set on 2D physics, rotation of the 3D ball is <a href="http://www.gfycat.com/ImperturbableQuickBuzzard" target="_blank">no longer automatic</a>. Lame. Let's use Unity scripting to manually rotate the ball as it moves in a 2D physics environment.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h2 style="clear: both; text-align: left;">
BallRoll Unity Project</h2>
<div class="separator" style="clear: both; text-align: left;">
The Unity 5.1 project <b>BallRoll</b> rotates a 3D ball using 2D physics. I have put source code on GitHub:</div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://github.com/KWarp/BallRoll">https://github.com/KWarp/BallRoll</a></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: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRIROu2y1wh0Rjz5X2Ssu9P0428efk_phH-jwX5IT49x66BRBZoIcHcMC3YJzQbpdbvziP_ICzazbpbGs-_n7O_j5s8UdhwShrbIDA8lH8YfK4T5NEUc8VzFJDArnsR7LE5oVz/s1600/soccer1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRIROu2y1wh0Rjz5X2Ssu9P0428efk_phH-jwX5IT49x66BRBZoIcHcMC3YJzQbpdbvziP_ICzazbpbGs-_n7O_j5s8UdhwShrbIDA8lH8YfK4T5NEUc8VzFJDArnsR7LE5oVz/s320/soccer1.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The main scene has a PlayerBall controlled by the arrow keys. There are also 3 PropBalls for you to bash into.</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/AVvXsEhQQlYaGsRyoATYajczMoM0ZwRqhHQoEgc4RL5wIpsWEb0M0UH_xfT-NZ6P5JeKuIHe74G4FOuiJNTryKxN71epFVQRez7tEXhlH6X0T9Ma4hDHz-E_0nphzRHR6DEkJsdvV8KJ/s1600/playerballselect.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQQlYaGsRyoATYajczMoM0ZwRqhHQoEgc4RL5wIpsWEb0M0UH_xfT-NZ6P5JeKuIHe74G4FOuiJNTryKxN71epFVQRez7tEXhlH6X0T9Ma4hDHz-E_0nphzRHR6DEkJsdvV8KJ/s320/playerballselect.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;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhonIA1syUIYs6PVoXjIhiB0N79Wq-f-8h1XUSIWajlA4fh9DLpw034NbBDu1ZUFmlNf-JYtMKV5WxQXAS6fzh9gQDyzu64T6iL3HUmZTh-LCtX6JYCmWFYYY89wYc4c7nRgDar/s1600/playerbsallcomponents.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhonIA1syUIYs6PVoXjIhiB0N79Wq-f-8h1XUSIWajlA4fh9DLpw034NbBDu1ZUFmlNf-JYtMKV5WxQXAS6fzh9gQDyzu64T6iL3HUmZTh-LCtX6JYCmWFYYY89wYc4c7nRgDar/s640/playerbsallcomponents.png" width="258" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Note that the PlayerBall has a <b>CircleCollider2D</b> and a <b>RigidBody2D</b>, and that the RigidBody2D is <b>constrained on the Z Rotation</b>. </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/AVvXsEhMeWHqmDd6vg_oj1z4HE2RrGE8Cx9apdm-srUBX1l8k3xBAW7IgT6Xa0Nsa9vfZHxZjBhoM-kkAw49R9sAPgxZNxEhE8YVeK4LEXGd5pBXespb0wny9xOx0g6FttHFb_48p_us/s1600/propballselect.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMeWHqmDd6vg_oj1z4HE2RrGE8Cx9apdm-srUBX1l8k3xBAW7IgT6Xa0Nsa9vfZHxZjBhoM-kkAw49R9sAPgxZNxEhE8YVeK4LEXGd5pBXespb0wny9xOx0g6FttHFb_48p_us/s320/propballselect.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimRBrpjYitSMXwurCjDuejowmRB13E4HuxZIoIK1kzyMmwisB6ccfJLKLcUY3Eaeeq0UJR8bNKkvp7QBFGgrvQ2g0zGGhzPMQvvdbOguir-6rS9TbX4ga26Af2Gl7CBLuDlYWE/s1600/propballcomponents.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimRBrpjYitSMXwurCjDuejowmRB13E4HuxZIoIK1kzyMmwisB6ccfJLKLcUY3Eaeeq0UJR8bNKkvp7QBFGgrvQ2g0zGGhzPMQvvdbOguir-6rS9TbX4ga26Af2Gl7CBLuDlYWE/s640/propballcomponents.png" width="298" /></a></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;">
PropBalls are the same as the player, with a different color, and minus the <b>BallInput</b> script.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h2 style="clear: both; text-align: left;">
Scripting Magic</h2>
<div class="separator" style="clear: both; text-align: left;">
First, we have a script that moves the ball with the arrow keys:</div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://github.com/KWarp/BallRoll/blob/master/Assets/Scripts/BallInput.cs">https://github.com/KWarp/BallRoll/blob/master/Assets/Scripts/BallInput.cs</a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Next, we have a script that rotates the ball as it moves. The critical part is the <b>rotateBall()</b> method that utilizes <b>Quaternions</b>:</div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://github.com/KWarp/BallRoll/blob/master/Assets/Scripts/BallRotation.cs">https://github.com/KWarp/BallRoll/blob/master/Assets/Scripts/BallRotation.cs</a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h2 style="clear: both;">
Quaternions</h2>
<div class="separator" style="clear: both; font-size: medium; font-weight: normal;">
Unity uses Quaternions in all GameObjects to store their rotation information in 3D space. Specifically, <b>GameObject.transform.rotation</b>. </div>
<div class="separator" style="clear: both; font-size: medium; font-weight: normal;">
<br /></div>
<div class="separator" style="clear: both; font-size: medium; font-weight: normal;">
There are many benefits to using Quaternions for 3D rotation, but everything that makes them powerful also makes them difficult to understand. I like to imagine a Quaternion as a hand crank:</div>
<div class="separator" style="clear: both; font-size: medium; font-weight: normal;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNZzzltaFnF-q1-7y4GVY_GRFqfaSidVS3nrPKAANZEbuSHiuCS2c6PxRdRx06qT0P7mxff8voftrWooo71oDGenulfWKjmi3yBq88N6RpDinV3jCkxOl3ME9huOdQB_X8CWox/s1600/hand+crank.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNZzzltaFnF-q1-7y4GVY_GRFqfaSidVS3nrPKAANZEbuSHiuCS2c6PxRdRx06qT0P7mxff8voftrWooo71oDGenulfWKjmi3yBq88N6RpDinV3jCkxOl3ME9huOdQB_X8CWox/s320/hand+crank.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; font-size: medium; font-weight: normal;">
<br /></div>
<div class="separator" style="clear: both; font-size: medium;">
<span style="font-weight: normal;">Now stab the soccer ball straight through its center with the crank pole. That is the </span><b>axis of rotation</b>. Now turn the crank a little. That is the <b>angle theta</b> that the ball is rotated. A Quaternion literally stores these variables as the direction Vector [<b>x</b>, <b>y</b>, <b>z</b>], and angle <b>w</b>.</div>
<div class="separator" style="clear: both; font-size: medium; font-weight: normal;">
<br /></div>
<div class="separator" style="clear: both; font-size: medium; font-weight: normal;">
For the curious, I read through <a href="http://www.3dgep.com/understanding-quaternions/" target="_blank">this article</a> while implementing the ball rotation algorithm. It made for good bedtime reading.</div>
<div class="separator" style="clear: both; font-size: medium; font-weight: normal;">
<br /></div>
<div class="separator" style="clear: both; font-size: medium; font-weight: normal;">
Quaternions are pretty easy to handle in Unity. Let's figure out how they tick.</div>
<div class="separator" style="clear: both; font-size: medium; font-weight: normal;">
<br /></div>
<h2 style="clear: both; text-align: left;">
The rotateBall() Method</h2>
<div class="separator" style="clear: both; text-align: left;">
The <b>rotateBall()</b> method uses Vector Math and Geometry to build a rotation Quaternion. The Quaternion is then applied to the ball's <b>GameObject.transform.rotation </b>to rotate it.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
We begin with <b>transform.position</b>, <b>lastPosition</b>, and the ball's <b>radius</b>. First, we determine <b>currentToLast</b> and <b>segment</b>.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiABsblCAjw4rB62WzrtuKx8DQdessvrdQbrE7s6HgT_2twGQnk9Fiy9UgL0cAlhz1xWXyKsucMotWZhAzOQUWjAl_m0lXCn3owM3NpnLhQ-6TBlX8AvSyifL4u1onxfSULD2Wx/s1600/currentToLast2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="251" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiABsblCAjw4rB62WzrtuKx8DQdessvrdQbrE7s6HgT_2twGQnk9Fiy9UgL0cAlhz1xWXyKsucMotWZhAzOQUWjAl_m0lXCn3owM3NpnLhQ-6TBlX8AvSyifL4u1onxfSULD2Wx/s640/currentToLast2.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<pre class="brush:csharp;">
// distance the ball traveled between the last Update and this one
// we subtract the vectors in this order to use it as a direction vector later
Vector3 currentToLast = lastPosition - transform.position; </pre>
<br />
Vector Subtraction tells us that "lastPosition - transform.position" gives us a direction Vector <b>currentToLast</b> that points from <b>transform.position</b> to <b>lastPosition</b>.<br />
<br />
<pre class="brush:csharp;">// segment length that the ball rolled along its surface
float segment = currentToLast.magnitude;
if (segment == 0)
{
// no distance travelled, nothing to do
return;
}
</pre>
<br />
<div>
The Vector's magnitude tells us the distance the ball traveled, which we save as <b>segment</b>.<br />
<div>
<br /></div>
With <b>currentToLast</b> and <b>segment </b>calculated, we can determine the <b>axis of rotation</b>, and angle <b>theta</b>.<br />
<br />
<h3>
Axis of Rotation</h3>
<br />
We use the <a href="https://en.wikipedia.org/wiki/Cross_product">Cross Product</a> to determine the <b>axis of rotation</b>. Given two Vector3s, the <b>Cross Product</b> returns a Vector3 that is perpendicular to both of them.<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvI5tohmjn2_rauMFbKtReVJf0h2myWtNhbjtPzRnH0N6y-Jb8eJFD9-NOR45I2lrq2b4ovrcH9sT2gN3135NPClaDvkNWUp92Uae8uD5tlZCngYqQvU0umapeit4JTSSz7uMb/s1600/axis+of+rotation+3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="289" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvI5tohmjn2_rauMFbKtReVJf0h2myWtNhbjtPzRnH0N6y-Jb8eJFD9-NOR45I2lrq2b4ovrcH9sT2gN3135NPClaDvkNWUp92Uae8uD5tlZCngYqQvU0umapeit4JTSSz7uMb/s640/axis+of+rotation+3.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<br /></div>
To use the Cross Product, we need two direction Vector3s. The first is <b>currentToLast</b>, the second is <b>ballDown</b>, which points directly at the ground.<br />
<br />
<pre class="brush:csharp;">// define the down direction vector for the ball
// the ball rolls in the x and y directions,
// and positive z points to the ground
// Important: this is DIFFERENT from Vector3.down because Vector3 assumes
// a 3D world space where negative y is down
Vector3 ballDown = new Vector3(0, 0, 1);
// use Cross Product to find the axis of rotation
// https://www.mathsisfun.com/algebra/vectors-cross-product.html
Vector3 axis = Vector3.Cross(ballDown, currentToLast);
// Cross Product will fail if both vectors are parallel or perpendicular
if (axis == Vector3.zero)
{
// this should never happen because currentToLast.z is always 0
// but who knows where this code will be copy-pasted to...
return;
}
</pre>
<br />
Now that we know where to rotate the ball, let's see how far we need to rotate it.<br />
<br />
<h3>
Angle Theta</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj05eRXvjhvKIGg1ObUcDR4yWciqklZugGxVS9k4A6DB8nNVPPCHhJc0lXu2pBfI7MmIZZIaX3BU2NyHJCnKPRipBIWvYVkOsKLFzPQ9UegIMvYPgEdJcau_kFhCQZLFRRl0n0p/s1600/arc+length.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="307" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj05eRXvjhvKIGg1ObUcDR4yWciqklZugGxVS9k4A6DB8nNVPPCHhJc0lXu2pBfI7MmIZZIaX3BU2NyHJCnKPRipBIWvYVkOsKLFzPQ9UegIMvYPgEdJcau_kFhCQZLFRRl0n0p/s400/arc+length.png" width="400" /></a></div>
<br />
The ball traveled <b>segment</b> (aka s) distance in between Updates, which means that the ball must roll exactly <b>segment</b> distance along the its surface. We can figure out <b>theta</b> (aka <span style="font-family: Arial; font-size: 10.6666666666667px; white-space: pre-wrap;">θ</span>) using the <a href="http://www.mathopenref.com/arclength.html">Arc Length Formula</a>:<br />
<br />
<pre class="brush:csharp;">// arc length formula
// s = r * theta
// theta = s / r
// http://www.mathopenref.com/arclength.html
float theta = segment / radius; // in radians
float thetaDegrees = theta * 180 / Mathf.PI;
</pre>
<br />
With <b>theta</b>, we know exactly how many degrees to rotate the ball.<br />
<br />
<h3>
Putting It All Together</h3>
<br />
Now that we know <b>theta</b> and <b>axis</b>, we politely squeeze them into a Quaternion:<br />
<br />
<pre class="brush:csharp;">Quaternion q = Quaternion.AngleAxis(thetaDegrees, axis);
</pre>
<br />
With our rotation Quaternion defined, we multiply it into the ball's <b>transform.rotation</b><br />
<br />
<pre class="brush:csharp;">transform.rotation = q * transform.rotation;
</pre>
<br />
Multiplication order is <b>crucial</b>. Quaternions, like Matrices, have Non-Commutative multiplication. Switch them up, and you'll get some weird results.<br />
<br /></div>
<h2 style="clear: both; text-align: left;">
Finally</h2>
<div class="separator" style="clear: both; text-align: left;">
Let's see what the end result looks like:</div>
<div class="separator" style="clear: both; text-align: left;">
<a href="http://www.gfycat.com/ShorttermFortunateFanworms" target="_blank">Ball Roll Result</a></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;">
BAM. DONE. YOU'RE WELCOME.</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;">
Thanks to <a href="http://opengameart.org/" target="_blank">OpenGameArt</a> for:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ol>
<li>The soccer field by <a href="http://opengameart.org/content/football-pitch" target="_blank">amon</a></li>
<li>The neat repeating texture by <a href="http://opengameart.org/content/free-tiling-textures-pack-55" target="_blank">nobiax</a></li>
</ol>
<br />
<br />Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-24941170793599444822014-08-09T20:30:00.000-07:002015-07-19T22:09:28.922-07:00Crypt of the Necrodancer: Dance Pad Setup Tutorial<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVHM6FYHRFhrXpbIFXTHuLW8GEq5bhbLluxOtNPlXAs_pUC2RzQ7nTlIji7cwoY8OmwKpVrcTArxBKgA_jlkUABlHOXkK76cg1LFbdrNshwKoJ6LbGSWHGZeibMt8fYQLAMGqQ/s1600/2599768-mainmenu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="425" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVHM6FYHRFhrXpbIFXTHuLW8GEq5bhbLluxOtNPlXAs_pUC2RzQ7nTlIji7cwoY8OmwKpVrcTArxBKgA_jlkUABlHOXkK76cg1LFbdrNshwKoJ6LbGSWHGZeibMt8fYQLAMGqQ/s640/2599768-mainmenu.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<a href="http://necrodancer.com/" target="_blank">Crypt of the Necrodancer</a> is an amazing game. I love the rythm-driven mechanics, and how it lends itself to play on a Dance Pad. While my reflexes are best with the keyboard Arrow Keys, I bought the <a href="http://dancepadmania.com/2013/02/26/deluxe/" target="_blank">Deluxe D-Force Dance Pad</a> for a bit of exercise, and novelty at parties.<br />
<br />
<a name='more'></a><br /><br />
By default, the Dance Pad and Arrow Keys are different button inputs, so swapping controllers means tweaking custom settings within the game each time.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZRf3fd8f9ErkkM3Hc7puynnLqAnBaEW9r3k1UJ-VUXSEOB6bwWRJVQntkUwCk17KQMawcqiCODgxszWJwQK6W6wMo-wD7ifOzGM0qQb9Vk7HpAy_mzlrgU5nzP20_QVLASjWC/s1600/Screen+Shot+2014-08-10+at+12.45.13+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="330" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZRf3fd8f9ErkkM3Hc7puynnLqAnBaEW9r3k1UJ-VUXSEOB6bwWRJVQntkUwCk17KQMawcqiCODgxszWJwQK6W6wMo-wD7ifOzGM0qQb9Vk7HpAy_mzlrgU5nzP20_QVLASjWC/s1600/Screen+Shot+2014-08-10+at+12.45.13+AM.png" width="400" /></a></div>
<br />
<br />
This is inconvenient, so I found a way to make the Dance Pad keys act like the Arrow Keys on Mac OS X.<br />
<br />
These steps will definitely work for the D-Force Dance Pad on Mac OS X. With any luck it should apply easily to other Dance Pads and Game Pads.<br />
<br />
<h2>
Download and Install Enjoy2</h2>
<a href="http://nongraphical.com/2012/08/enjoy2-mapping-joystick-inputs-to-keyboard-and-mouse-events/" target="_blank">Enjoy2</a> is a simple program to map joystick inputs to keyboard and mouse events. Visit <a href="https://github.com/fyhuang/enjoy2/" target="_blank">this github page</a> and scroll down to "How To Install" to find the download link.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8eV-xLAKoINWO2HfLvdbV43kNHue7-URjyc1kZVwn9Dx4MGGoyHSpQsAA1O41xl4-aSbAHcYI1NAUEdXFi8bbxl3vJlQ1cEMrjuUFWVTFMwWIRMHb6oID5gksdjZvcgD4fd7N/s1600/enjoy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8eV-xLAKoINWO2HfLvdbV43kNHue7-URjyc1kZVwn9Dx4MGGoyHSpQsAA1O41xl4-aSbAHcYI1NAUEdXFi8bbxl3vJlQ1cEMrjuUFWVTFMwWIRMHb6oID5gksdjZvcgD4fd7N/s1600/enjoy.png" /></a></div>
<br />
Once the zip file is downloaded and opened, drag and drop "Enjoy2.app" into your "Applications" folder (so that you don't delete it accidentally later).<br />
<br />
<br />
<h2>
Configure Dance Pad Inputs</h2>
Now, open Enjoy2.app. It might fail to open because of your Mac Security Settings. If so, go to "System Preferences" -> "Security & Privacy" and change "Allow Apps Downloaded from" to "Anywhere"<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4caNRPqMER0HUFuQLXD8a2qIZZ_PWmVqqGH2OrD9Z-iJal25ko3LcgBXmd7zfLI8gJen1g_QnqGjw01oMGQfL8z281SJZaJr4JTjgUX8ef8ghp5ST1tXgOKd8sFoRwslDc-lG/s1600/Screen+Shot+2014-08-10+at+1.57.50+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4caNRPqMER0HUFuQLXD8a2qIZZ_PWmVqqGH2OrD9Z-iJal25ko3LcgBXmd7zfLI8gJen1g_QnqGjw01oMGQfL8z281SJZaJr4JTjgUX8ef8ghp5ST1tXgOKd8sFoRwslDc-lG/s1600/Screen+Shot+2014-08-10+at+1.57.50+AM.png" width="400" /></a></div>
<br />
Apple will warn you that this makes your computer less secure. Oh well...<br />
<br />
Plug in your USB Dance Pad if you haven't already. You should see something like this in Enjoy2:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbqoDaZpxF-eSwCv05pSyQOmRNUVNZ1dwkh9kqFsfDXmy-RNohKvL0d4Tf1EcV55IoyRXfiqfWylOVwc0-yt1XZxeuElPvSN1KiizjWXIhO58cjvUvl6bVvE-nqBBOU43z5MvL/s1600/Screen+Shot+2014-08-10+at+2.03.02+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbqoDaZpxF-eSwCv05pSyQOmRNUVNZ1dwkh9kqFsfDXmy-RNohKvL0d4Tf1EcV55IoyRXfiqfWylOVwc0-yt1XZxeuElPvSN1KiizjWXIhO58cjvUvl6bVvE-nqBBOU43z5MvL/s1600/Screen+Shot+2014-08-10+at+2.03.02+AM.png" width="400" /></a></div>
<br />
<br />
Press the "Configurations" button in the top-left to open the drawer. I named my Configuration "Necrodancer DForce" so that I remember what it is in a few months.<br />
<br />
Setting up each key is easy:<br />
<ol>
<li>Tap a button on your Dance Pad </li>
<li>Tap the Keyboard Key you want it to map to</li>
<li>Repeat for each button on your dance pad</li>
</ol>
<div>
<br /></div>
<h2>
Activate The Configuration</h2>
<div>
In Enjoy2, press the "Start" button (next to the "Configuration" button) to activate the keyboard mapping. It should work instantly. Anywhere you use the arrow keys, the Dance Pad keys will work as well!<br />
<br />
<br /></div>
<h2>
Every Time That You Play With The Dance Pad</h2>
<div>
<ol>
<li>Plug in your USB Dance Pad</li>
<li>Open Enjoy2 and start the configuration</li>
<li>Open Crypt of the Necrodancer</li>
</ol>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<br />
<br />Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-57547775745004829462011-12-04T00:21:00.001-08:002011-12-11T00:00:54.237-08:00Rapid Physics Beta Release<script src="http://alexgorbatchev.com/pub/sh/2.1.364/scripts/shCore.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/2.1.364/scripts/shBrushAS3.js" type="text/javascript">
</script> <script src="http://alexgorbatchev.com/pub/sh/2.1.364/scripts/shLegacy.js" type="text/javascript">
</script>
<link href="http://alexgorbatchev.com/pub/sh/2.1.364/styles/shCore.css" rel="stylesheet" type="text/css"></link>
<link href="http://alexgorbatchev.com/pub/sh/2.1.364/styles/shThemeDefault.css" rel="stylesheet" type="text/css"></link> <script language="javascript">
window.onload = function () {
dp.SyntaxHighlighter.ClipboardSwf = 'http://alexgorbatchev.com/pub/sh/2.1.364/scripts/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('code');
dp.SyntaxHighlighter.BloggerMode();
}
</script>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRXUsX4cb9BJ1jfrExnrUzGN-H7S5YX5RnAr2ez2CXIBcu0cMj2pRi8ZrDwafiiPlyoYpiUIaGbPEhy8KGDRw0U7j5QJb2EeM53N4LeAuPBmiF_h1-2cp3gTYk8jHxckOQUxks/s1600/rapid_physics_logo_128.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRXUsX4cb9BJ1jfrExnrUzGN-H7S5YX5RnAr2ez2CXIBcu0cMj2pRi8ZrDwafiiPlyoYpiUIaGbPEhy8KGDRw0U7j5QJb2EeM53N4LeAuPBmiF_h1-2cp3gTYk8jHxckOQUxks/s1600/rapid_physics_logo_128.png" /></a></div>
<br />
<br />
Rapid Physics is a custom Physics Engine that I decided to build in Flash.<br />
<br />
Why would I torture myself like that?<br />
<br />
There are plenty of industrial-strength physics engines out there, such as Havok and Box2D. They offer complete and robust physics simulations, but they also hide a lot of information from the programmers that use them. This leads to two problems:<br />
<ol>
<li>Hard limits on authorship control over the physics simulation (lots of code you didn't write)</li>
<li>A sense of helplessness when debugging engine-level problems (lots of code you didn't test)</li>
</ol>
<div>
Effectively, game programmers lose the granularity to control subtle features of the physics simulation, and the ability to do custom collision resolution for gameplay purposes. For games whose physics are integral to gameplay, there is still a place for custom physics implementations. </div>
<div>
<br /></div>
<div>
I designed Rapid Physics to tackle one specific problem that most general-purpose physics engines never attempt to address: Tunneling</div>
<div>
<br />
<br />
<a name='more'></a><br /></div>
<div>
<span class="Apple-style-span" style="font-size: large;">Tunneling</span></div>
<div>
In a physics simulation, physics objects actually teleport small distances each frame. The faster they move, the farther they teleport. Eventually, there comes a point where objects end up teleporting through other objects they should actually collide with. We call this problem Tunneling.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<span class="Apple-style-span" style="font-size: large;">What Rapid Physics Does</span></div>
<div>
Rapid Physics solves the tunneling problem for a fast-moving points that collide with Lines and Circles.</div>
<div>
<br /></div>
<div>
That's all?</div>
<div>
<br /></div>
<div>
For now, yes. The mathematical and algorithmic needs behind advanced collision detection are damned complicated. It turned out that perfecting such a simple task still takes hundreds of lines of code. Throw in some useful engine features, test code, and demos, and the codebase explodes to several thousand lines of code. That's a lot to do in a single semester!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbjEeU3ESWOaLv2V48-FWoHWv6ddC_48cTgBKvz3YmkteuTifxOwsdhaihuV0cSCnA8pb8UihS_ZI4jXo7w51eDJSEvWcj0brJ7Ggwj0bx1UDlQzT5oQzlI82l9P3J9Qs5jPuG/s1600/shot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbjEeU3ESWOaLv2V48-FWoHWv6ddC_48cTgBKvz3YmkteuTifxOwsdhaihuV0cSCnA8pb8UihS_ZI4jXo7w51eDJSEvWcj0brJ7Ggwj0bx1UDlQzT5oQzlI82l9P3J9Qs5jPuG/s1600/shot.png" /></a></div>
<br />
Check out the Beta Release here:<br />
<a href="http://kwarp.com/portfolio/rapidphysics.html">http://kwarp.com/portfolio/rapidphysics.html</a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<span class="Apple-style-span" style="font-size: large;">How Rapid Physics Works</span></div>
<div>
Rapid Physics is heavily inspired by the Flixel 2.5 framework. If you know how to use Flixel, you will know how to write in RapidPhysics. Here is a handy guide of some Flixel equivilents:</div>
<div>
<ul>
<li>FlxGame - RapidSim</li>
<li>FlxG - RapidG</li>
<li>FlxU - RapidU</li>
<li>FlxState - RapidWorld</li>
<li>FlxBasic - RapidBasic</li>
<li>FlxObject - RapidObject</li>
<li>FlxGroup - RapidGroup</li>
<li>FlxText - RapidText</li>
<li>Input - (literally the same code, use RapidG.keys)</li>
</ul>
</div>
<div>
<a href="https://github.com/AdamAtomic/flixel/wiki/Flixel-Organization-Overview">Flixel's Design overview</a> applies equally well to RapidPhysics. The class where your game starts will extend RapidSim. The class where you write most of your physics code will be a class that extends RapidWorld. Exactly one RapidWorld exists at a time, and it's easy to switch between worlds with a call to host.switchWorld() (every RapidWorld has a host property).</div>
<div>
<br /></div>
<div>
Next, let's discuss some of the core components of Rapid Physics:</div>
<div>
<br />
<br /></div>
<div>
<span class="Apple-style-span" style="font-size: large;">Islands</span></div>
<div>
In Rapid Physics, Islands do all of the heavy lifting of the physics simulation. The idea is as follows:</div>
<div>
<ol>
<li>Add all of your RapidObjects to an Island</li>
<li>Add your Island to the RapidWorld's IslandManager</li>
<li>Enjoy sexy physics</li>
</ol>
<div>
The base class Island contains that core algorithm that solves collisions in Rapid Physics. Subclasses of island simply define what kinds of objects are collected together for collision solving. Currently, there are exactly 2 Islands in Rapid Physics:</div>
<div>
<ul>
<li>PointLineIsland</li>
<li>PointCircleIsland</li>
</ul>
<div>
Let's take a look at PointLineIsland, for example:</div>
<div>
<br /></div>
<pre class="brush: as3" name="code">package org.rapidphysics.islands
{
import flash.geom.Point;
import flash.utils.Dictionary;
import org.rapidphysics.Collision;
import org.rapidphysics.RapidU;
import org.rapidphysics.Rlap;
import org.rapidphysics.shapes.RapidLine;
import org.rapidphysics.shapes.RapidPoint;
/**
* An Island that solves collisions between moving points and fixed lines.
* @author greglieberman
*
*/
public class PointLineIsland extends Island
{
public var points:Vector.<rapidpoint>;
public var lines:Vector.<rapidline>;
public function PointLineIsland()
{
super();
points = new Vector.<rapidpoint>();
lines = new Vector.<rapidline>();
}
/**
* This is an implementation of collectCollisions for points and lines
* NOTE WELL: This implementation collides every point with every line, but it does NOT collide points with each other, or lines with each other
* @param frameTime
*
*/
protected override function collectCollisions(frameTime:Number):void
{
var temp:Point = new Point();
// test for collision between every point and every line
for each(var rPoint:RapidPoint in points)
{
for each(var line:RapidLine in lines)
{
var result:Point = (Rlap.lineSegments(rPoint.position, rPoint.nextPosition, line.position, line.end, temp));
if(result)
{
// grab a collision object, and fill it with data from the intersection
var c:Collision = recycleCollision();
c.init(rPoint, line, Rlap.resolveMovingPointAndFixedLine); // obj1, obj2, how to resolve the collision
c.pointOfCollision.x = result.x;
c.pointOfCollision.y = result.y;
c.time = frameTime + RapidU.timeOfCollision(rPoint.position, rPoint.nextPosition, result); // define time for priority in solving collisions
addCollision(c);
}
}
}
}
}
}
</rapidline></rapidpoint></rapidline></rapidpoint></pre>
<br />
At it's core, it's just two Vectors, and 2 nested for loops. Not too bad right?
<br />
<div>
<br />
It should be extremely easy to write new Island subclasses with the existing intersection tests, should you have more custom collision needs. The tough part is writing brand new intersection tests. I could spend another semester just working on those...<br />
<br />
<br />
<span class="Apple-style-span" style="font-size: large;">The Core Collision Algorithm</span><br />
The core collision-solving algorithm is perfect, but <b>extremely expensive</b>. Here's what it does:<br />
<br />
Every Island, every frame:<br />
<ol>
<li>Test for collisions</li>
<li>Sort collisions by time</li>
<li>Resolve collisions in time order</li>
<ol>
<li>Every time Step 3 occurs, throw out all collision information, and return to Step 1.</li>
</ol>
</ol>
</div>
</div>
</div>
<div>
This is insane, but necessary. When a collision is solved, it changes the state of the system, so every object that is being tested for collision needs to be evaluated again. In the worst case (which <i>never</i> happens), you are looking at a runtime of O(n!). The only way to avoid this is to cheat the physics in some way. Thankfully, in general, you are looking at an average runtime of O(n^3). This can be even faster if the collision test code runs better than O(n^2).<br />
<br />
<br />
<span class="Apple-style-span" style="font-size: large;">Intersection Tests</span><br />
I designed Rapid Physics in parallel with a game that I am building. I wanted to utilize parts of Rapid Physics immediately during development, so there are 2 components to the engine that are extremely easy to integrate into to other games: Rlap and RapidU.<br />
<ul>
<li>Rlap contains the hardcore Intersection Tests, and also Collision Resolution functions</li>
<li>RapidU contains low-level utility functions, like clamp, vector reflection, dot product, etc.</li>
</ul>
<div>
Intersection tests are some of the hardest parts of physics programming. I hope they serve you well.<br />
<br /></div>
<div>
<br /></div>
<div>
<br />
<div>
<span class="Apple-style-span" style="font-size: large;">Setup</span><br />
For project setup, I strongly recommend importing RapidPhysics into a Flash Builder project. For this, Flixel has a <a href="http://flashgamedojo.com/wiki/index.php?title=Hello_World_-_Flash_Builder_(Flixel)">nice setup guide</a>.<br />
<br />
Download the source files on GitHub:<br />
<a href="https://github.com/KWarp/Rapid-Physics">https://github.com/KWarp/Rapid-Physics</a></div>
<div>
<br /></div>
<div>
Unlike Flixel, RapidPhysics is not a complete game engine. You will probably be better off exploring and modifying the five project demos instead of building something from scratch.<br />
<br />
You can find the code documentation in the GitHub repository, but for convenience, you can also find it here:<br />
<a href="http://kwarp.com/docs/rapidphysics/">http://kwarp.com/docs/rapidphysics/</a><br />
<br /></div>
</div>
<br />
<span class="Apple-style-span" style="font-size: large;">Conclusion</span><br />
That's a wrap for this Beta Release. Maybe I'll add more to this project in the future.<br />
<br />
PEACE</div>
<div>
<br /></div>Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-43194956456464862692011-09-20T02:10:00.000-07:002011-09-20T02:14:53.956-07:00Rapid PhysicsI am building a physics engine called Rapid Physics. It is designed to correctly simulate objects that move <b>really fast</b>. This is difficult problem that is commonly known as the <a href="http://www.aorensoftware.com/blog/2011/06/01/when-bullets-move-too-fast/">tunneling problem</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNo0ph7Mc85U6E0TMO4iWzoNohEZuz-3QYd_GJdY6hWgvRq-QggwIAMZo3YpTibrV4qcUpa8-DMGJKwyMNtXnG4xTdBp-pQYzYUo2EEBRD_6AjXF2EF-4g6a9KevClRmStATwx/s1600/rapid+screen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="297" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNo0ph7Mc85U6E0TMO4iWzoNohEZuz-3QYd_GJdY6hWgvRq-QggwIAMZo3YpTibrV4qcUpa8-DMGJKwyMNtXnG4xTdBp-pQYzYUo2EEBRD_6AjXF2EF-4g6a9KevClRmStATwx/s400/rapid+screen.png" width="400" /></a></div>
<br />
<br />
Check out a quick demo here:<br />
<a href="http://kwarp.com/downloads/blogdownloads/rapidphysics025/RapidPhysics.html">Rapid Physics 0.25 Alpha</a><br />
<br />
<br />
<br />Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-34117651986182095732011-09-16T10:52:00.000-07:002011-09-16T10:52:48.446-07:00Developer BlogI'm running a developer blog on <a href="http://bullettimeninja.blogspot.com/">Bullet Time Ninja</a>. Check it out!Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-50125552813209453812011-06-14T13:26:00.000-07:002011-06-27T00:43:12.593-07:00E3 2011<img src="http://www.gogaminggiant.com/wp-content/uploads/2011/05/E3-Logo-Header.jpg" style="-webkit-user-select: none;" /><br />
<br />
A few weeks ago, I received an amazing phone call that would change my life (for a week).<br />
<br />
I became an IGDA E3 Scholar!<br />
<br />
What's that you ask?<br />
<br />
Let's break it down. First, the <b>IGDA</b> is an official support group for game developers. Here is their official About statement from IGDA.org:<br />
<blockquote><span class="Apple-style-span" style="font-family: 'trebuchet ms', geneva; font-size: 13px; font-style: italic; line-height: 19px;">The International Game Developers Association is the largest non-profit membership organization serving individuals who create video games. We bring together developers at conferences, in local chapters and in special interest groups to improve their lives and craft.</span></blockquote>The Electronic Entertainment Expo, or <b>E3</b>, is the largest media gathering in the Videogame Industry. Every major game studio and platform holder uses E3 as a venue to announce their next big thing.<br />
<br />
As an IGDA E3 Scholar, I got a pretty sweet deal:<br />
<br />
<ul><li>Pre-paid E3 ticket ($500 value)</li>
<li>Access to the press events from Sony, Microsoft, Nintendo, EA, and Ubisoft.</li>
<li>Tours of several game studio booths on the show floor</li>
<li>A couple lunches with various game developers</li>
<li>Some 2nd floor access</li>
<li>A field trip to the CAA, and EALA</li>
<li>Doing all of the above in the company of 14 other IGDA E3 Scholars. </li>
</ul><div>It was the most epic E3 a person could ever hope for. I am extremely grateful to the IGDA for this incredible opportunity to network and learn from my peers. Below, in no particular order, are some of my most vivid memories from the event:</div><div><br />
</div><div>During a developers lunch, I spoke with an EA programmer about game engine architectures. My specific interest was what comes first in a professional GameObject class hierarchy: rendering or physics? To illustrate my question more clearly, would the class inheritance hierarchy look like this:</div><div><ul><li>GameObject</li>
<li>RenderingObject</li>
<li>PhysicsObject</li>
</ul></div><div>Or this?</div><div><ul><li>GameObject</li>
<li>PhysicsObject</li>
<li>RenderingObject</li>
</ul></div><div>The professional convention seems to be one of two things: they either both occur at the same level, or an object-compositional model is used, where a RenderingObject owns a PhysicsObject. The latter model is especially useful in games where a 3rd-party physics engine like Havok is employed.</div><div><br />
</div><div>Microsoft made a bunch of Kinect-related announcements during their E3 press conference, one of which was the use of Voice Commands in Mass Effect 3. I was giggling to myself as this was presented, as I had already <a href="http://commandthebridge.com/">beaten Bioware to the punch</a> with my Voice Command game, The Bridge. We wrapped up that project last month. :D</div><div><br />
</div><div>For the record, the experience of physically speaking Voice Commands to a game character, and then having that character respond appropriately, feels really amazing. It will be a killer addition to the Mass Effect 3 experience that everyone should try at least once.</div><div><br />
</div><div>Tim Schaffer is hilarious.</div><div><br />
</div><div>Sony had a good press conference. The Playstation-branded 3DTV for $500 looked really damn nice. </div><div><br />
</div><div>I managed to show my <a href="http://bullettimeninja.blogspot.com/">Bullet Time Ninja</a> game in video form to quite a few game developers on the show floor. Reactions ranged from "pretty neat" to "omg that's really awesome!!", so I'm pleased as punch. :)</div><div><br />
</div><div>A few quick blurbs on games that I played:</div><div><ul><li>Fruit Ninja for Kinect is everything that I have ever wanted from a Kinect game.</li>
<li>Skulls of the Shogan looks like a good Indie game. There are a few game design kinks, but I am optimistic that they will be addressed before release.</li>
<li>SkullGirls has the greatest art and animation that I have ever seen in a fighting game. Must buy!</li>
<li>Monaco is really fun, but I feel like the current pixel art is holding the game back. I had a difficult time initially learning what was important on screen. Some focused art direction will turn that game from Great to Incredible.</li>
<li>I was outright impressed by the new XCOM game. The art style is right on the mark.</li>
<li>Kirby Wii is the most fun Kirby game I that have ever played.</li>
<li>The Wii U demos were pretty neat. I have high hopes.</li>
</ul></div><div><br />
</div><div>Videogames Live had a great show this year. The Chrono Trigger performance was beautifully done. Have a listen: <a href="http://www.youtube.com/watch?v=UV2RKqmCs4w">http://www.youtube.com/watch?v=UV2RKqmCs4w</a></div><div><br />
</div><div>Overall, this was the greatest E3 experience I have ever had. The IGDA is doing a great service for up and coming students. I hope future generations of amazing game designers get the same opportunities.</div><div><br />
</div><div>Thanks for reading,</div><div>Greg</div><div></div><div><br />
</div><div><br />
</div>Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-1678620622565591932011-06-01T12:25:00.000-07:002011-06-26T01:25:41.027-07:00Empires & Allies<div class="separator" style="clear: both; text-align: center;"><a href="http://www.gev.com/wp-content/uploads/2011/06/empires-allies-logo-.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="297" src="http://www.gev.com/wp-content/uploads/2011/06/empires-allies-logo-.jpg" width="320" /></a></div><br />
I started my internship at Zynga Los Angeles last week. We are working on a cool game called Empires & Allies. I think it's the best Zynga game yet.<br />
<br />
While most Zynga games have you building some kind of farm or city, in Empires & Allies you are building an army. Make buildings, produce units, and take them battle. There's a pretty lengthy single-player campaign, and you can also invade your neighbors and take their resources.<br />
<br />
The most interesting part of this game is the incredible sophistication of it's economy. I have never seen a game with a remotely comparable amount of interlocked systems. Let's list out every resource there is:<br />
<br />
<ul><li>Coins</li>
<li>Empire Points</li>
<li>XP</li>
<li>Energy</li>
<li>Wood</li>
<li>Oil</li>
<li>Liberty Bonds</li>
<li>Ore Types</li>
<ul><li>Aluminum</li>
<li>Uranium</li>
<li>Iron</li>
<li>Gold</li>
<li>Copper </li>
</ul><li>Population</li>
<li>Neighbors</li>
<li>Units</li>
<li>Time - (a component to everything)</li>
</ul><div><br />
We've seen a lot of these resources in previous Zynga games. Let's talk about the new ones.</div><div><ul><li><b>Wood</b>: A resource limiter on how quickly you can make buildings. Simple enough, and quite clever.</li>
<li><b>Oil</b>: A resource limiter on how quickly you can make military Units.</li>
<li><b>Ore types</b>: The player is randomly given one kind of Ore type that can be produced within his or her empire. Players must trade with their neighbors to get other types of Ore. Ore is mostly required to produce certain kinds of units and buildings.</li>
<li><b>Units</b>: The most significant new resource. Units you make can be taken to battle. When units die, they are permanently gone, and new ones must be produced.</li>
</ul></div><div><br />
</div><div>The problem I have with many Zynga games is that after playing them for a few days, I amass so many buildings and resources, that I stop caring about my resources altogether. This is why I find Units in Empires & Allies so fascinating. A Unit is a resource that I can lose. The more I play the game, the more I burn Units in combat. In response, I deposit my hard-earned Coins, Oil, and Ore to replace them. It's a great cycle that will keep me running a tight economy for the lifetime of my gameplay sessions. Plus, units exist in several tiers. As I unlock new ones, I always have something to build.</div><div><br />
</div><div>Empires & Allies looks to be a fantastic addition to the Zynga portfolio. I am thrilled to be working on it.</div><div><br />
</div><div><br />
</div>Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-87292123594498057362011-05-09T23:28:00.000-07:002011-06-26T00:09:21.284-07:00The Bridge Wrap-Up<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1z0dNtJ6cnWVAlbYbRmB23nrgCmK34jmHqKl5R8OJbtZAHUscyDcvIdNlCov2zgWLxvqRS1bnBGZcZFdN9BWdCkM9H0CRTOM75ioA7zXzVTVZZeJUSBJ8fTPhJO9qwYw8bOsB/s1600/Insignia-1280x960.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1z0dNtJ6cnWVAlbYbRmB23nrgCmK34jmHqKl5R8OJbtZAHUscyDcvIdNlCov2zgWLxvqRS1bnBGZcZFdN9BWdCkM9H0CRTOM75ioA7zXzVTVZZeJUSBJ8fTPhJO9qwYw8bOsB/s320/Insignia-1280x960.png" width="320" /></a></div><br />
<br />
Work has wrapped up on The Bridge. Big thanks to the team and everyone who supported us.<br />
<br />
Here's our awesome website:<br />
<a href="http://commandthebridge.com/">http://commandthebridge.com/</a><br />
<br />
Here's a live demonstration of the final game:<br />
<a href="http://www.youtube.com/watch?v=uW5x6AyL7Cw">http://www.youtube.com/watch?v=uW5x6AyL7Cw</a><br />
<br />
We were featured on ABC 7 News:<br />
<a href="http://abclocal.go.com/kabc/video?id=8113138">http://abclocal.go.com/kabc/video?id=8113138</a><br />
<br />
We were also featured at TEDxUSC:<br />
<a href="http://www.facebook.com/media/set/?set=a.10150217517612037.355868.509387036&l=9a2c67f60c">http://www.facebook.com/media/set/?set=a.10150217517612037.355868.509387036&l=9a2c67f60c</a><br />
<br />
<br />
What an awesomely fun project.Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-91827712065012448532011-01-31T23:31:00.000-08:002011-01-31T23:31:14.285-08:00Global Game Jam 2011I made an awesome Tron-style game for Global Game Jam 2011<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://kwarp.com/portfolio/fightfortheusers.html" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdSQZMzSJOARTT1vqfVWRNAtFWvjU1t-J7TNzJParOOjhqHtOvChC1Zf54LRXSTfb5OclEA_XhW6pM6pC_YBtXURtTnBIyJ7AKVBvTVBQVfYsZ6VJ59kYp9MfLAmegIFTIe-jj/s400/screenshot.jpeg" width="400" /></a></div><br />
<br />
Play the game here:<br />
<a href="http://kwarp.com/portfolio/fightfortheusers.html">http://kwarp.com/portfolio/fightfortheusers.html</a><br />
<br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Team page here:</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><a href="http://www.globalgamejam.org/2011/fight-user">http://www.globalgamejam.org/2011/fight-user</a></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div>Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-68626750556763066322011-01-26T15:48:00.000-08:002011-01-26T15:48:58.088-08:00Demo DayEach semester, USC hosts a Demo Day where Computer Science Games students present their game projects to professionals in the industry. In December 2010, I presented <a href="http://commandthebridge.com/">The Bridge</a> on behalf of my team. The media coverage has just been released, which you can check out here:<br />
<br />
<a href="http://viterbi.usc.edu/news/news/2010/gamepipe-lab-hosts.htm">http://viterbi.usc.edu/news/news/2010/gamepipe-lab-hosts.htm</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="http://viterbi.usc.edu/news/news/2010/gamepipe-lab-hosts.htm"><img border="0" height="310" src="http://viterbi.usc.edu/assets/120/72719.jpg" width="320" /></a></div><br />
The picture of me in the article is nothing short of ridiculous. :PGreg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-33577014934146326152011-01-24T02:22:00.000-08:002011-01-24T02:22:40.291-08:00Microsoft Word Makes Me Sad<div style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqlFmTqURTRkKxFOwhsfWOUd7xEtjnjDqoQbFpr98FCd6kmUECT9EMMGIwIyLOVOeATwyxvpsOgc4cvU5xLrFD99CUdCqUP3V1KxKvdiNdzNm9GzWyNRhUk12O2jczZP5CRRCs/s1600/word-icon.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqlFmTqURTRkKxFOwhsfWOUd7xEtjnjDqoQbFpr98FCd6kmUECT9EMMGIwIyLOVOeATwyxvpsOgc4cvU5xLrFD99CUdCqUP3V1KxKvdiNdzNm9GzWyNRhUk12O2jczZP5CRRCs/s1600/word-icon.png" /></a></div><br />
I have a love/hate relationship with Microsoft Word. I trust it to get my work done securely and professionally, but my day-to-day experience with the product is often plain frustrating.<br />
<br />
Take for example, this outline I began putting together in Microsoft Word 2008 for Mac<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGHvOc8WPC37xd74-RWDeShM_u8K3oMG2vmm7VOV6WyOO-AT5HyBZzYUWAiE6qqQFNyM28jvNAjHJJNVDxbXX9Inhq3lVS24ZUu2vWu8HbO2KRtn4sizd1a4y99j26GbbBbaN-/s1600/Screen+shot+2011-01-24+at+2.07.14+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="95" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGHvOc8WPC37xd74-RWDeShM_u8K3oMG2vmm7VOV6WyOO-AT5HyBZzYUWAiE6qqQFNyM28jvNAjHJJNVDxbXX9Inhq3lVS24ZUu2vWu8HbO2KRtn4sizd1a4y99j26GbbBbaN-/s320/Screen+shot+2011-01-24+at+2.07.14+AM.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;">I have pasted a URL, and want to make it a hyperlink. How can I do that?</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVwfCeB7JBTjcosO0y13ikURl5Ls8vuhUqt82LiS0_pkitM3kD3Dv2aFnjpIh549VBazOYjgRhjZ_6-h5kasOoOPy0gVKTZOZRzFKiRieI68kPgOdvZKpAQcGdNNKD1_WC0dUE/s1600/Screen+shot+2011-01-24+at+2.07.28+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVwfCeB7JBTjcosO0y13ikURl5Ls8vuhUqt82LiS0_pkitM3kD3Dv2aFnjpIh549VBazOYjgRhjZ_6-h5kasOoOPy0gVKTZOZRzFKiRieI68kPgOdvZKpAQcGdNNKD1_WC0dUE/s320/Screen+shot+2011-01-24+at+2.07.28+AM.png" width="306" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Ah yes, there it is, in this huge menu. Let's select the Hyperlink option.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikO_V75PjwiTBtlhIwRjeQAffjFFtmCf6dLC4Q0iLfjf1d5BBLWFRaCtsXgmJAElxJ1Rr_Dc8kkExKmcn5j9L6dATJKRFTMPF7vUGpTNA-__CDl5oojYh0PhJjDjbeq27-ak9R/s1600/Screen+shot+2011-01-24+at+2.07.43+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikO_V75PjwiTBtlhIwRjeQAffjFFtmCf6dLC4Q0iLfjf1d5BBLWFRaCtsXgmJAElxJ1Rr_Dc8kkExKmcn5j9L6dATJKRFTMPF7vUGpTNA-__CDl5oojYh0PhJjDjbeq27-ak9R/s320/Screen+shot+2011-01-24+at+2.07.43+AM.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;">Whoa, a huge popup with tons of information I don't want to read. Let's press ok and see if it works...</div><div style="text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqNidzwaHYNr6YdpGPxf3mfkUP9_NSuJ0cdbc7KOmwLuOZJlBCrJmdoHzxbSA66Et0FIyglID2VUyNPVSzjAaIjj3Y5LD0ugNA96R1QvrYm2T4FZWiiA4pv1ag5sNw3yHVmYm_/s1600/Screen+shot+2011-01-24+at+2.07.54+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="81" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqNidzwaHYNr6YdpGPxf3mfkUP9_NSuJ0cdbc7KOmwLuOZJlBCrJmdoHzxbSA66Et0FIyglID2VUyNPVSzjAaIjj3Y5LD0ugNA96R1QvrYm2T4FZWiiA4pv1ag5sNw3yHVmYm_/s320/Screen+shot+2011-01-24+at+2.07.54+AM.png" width="320" /></a></div><br />
It looks like the URL became a hyperlink, but it also screwed up my bullet point formatting.<br />
<br />
:(<br />
Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com2tag:blogger.com,1999:blog-23809115.post-79079872585117634082010-12-13T01:50:00.000-08:002010-12-13T01:51:07.802-08:00Vector MathI ran into a fun problem while working on The Bridge today:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL1BkRJUNNYo6zUwjXHeXFuKSUEXxKB6G_R6Rn-E6Lyd6wIVoYuSK3k6sirWixf3N2vVs1T3d2FuxkTau3cxiaBitWHpeRjtqRrBAUnNgSnHTJtf5xKFAzgwaBfWNkza-Ti0Hm/s1600/turn+clockwise.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL1BkRJUNNYo6zUwjXHeXFuKSUEXxKB6G_R6Rn-E6Lyd6wIVoYuSK3k6sirWixf3N2vVs1T3d2FuxkTau3cxiaBitWHpeRjtqRrBAUnNgSnHTJtf5xKFAzgwaBfWNkza-Ti0Hm/s320/turn+clockwise.PNG" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><br />
In my process of refactoring the ship engine, I added a rotational thruster to turn the ship. When the player issues a Turn Clockwise command, the Navigator AI will apply the rotational thruster to the ship until it reaches the desired velocity.<br />
<br />
Here are the properties I worked with:<br />
<ul><li>A target yaw, pitch, and roll to rotate to, in terms of angular velocity</li>
<li>Current angular velocity of the ship</li>
<li>Angular acceleration of the ship's engines</li>
</ul><div><br />
Each of these I represented as a Vector3 in XNA<br />
<div><ul><li>Vector3 targetAngularVelocity;</li>
<li>Vector3 currentAngularVelocity;</li>
<li>ship.engines.angularThrust</li>
</ul><br />
I figured that the most logical way to approach this was to adjust angularThrust every frame in an Update loop. The challenge was figuring out what acceleration was appropriate, when only given currentAngularVelocity and targetAngularVelocity.</div><div><br />
</div><div>My first attempt involved finding a midpoint vector with a simple LERP:</div><blockquote>ship.engines.angularThrust = Vector3.Lerp(currentAngularVelocity, targetAngularVelocity, strength) * time;</blockquote><div>This works when going from not rotating at all, to rotating in some direction. However, it fails miserably if the ship is already moving in some capacity. I ended up spinning the player's ship phenomenally fast.</div><div><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiMcoPfTaD3WX3seNv-6Sy-_EuhcGGmhT4yKQy3e2hOJUcK3wNGc8N46yUOX5aEL_5hgd2QqAnOsFHiXR6Vi4EPG-3qROzuvlD3ar6owxJyqOuBdoWTDb4DbcTs3NfLcb1FkGO/s1600/aok.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="130" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiMcoPfTaD3WX3seNv-6Sy-_EuhcGGmhT4yKQy3e2hOJUcK3wNGc8N46yUOX5aEL_5hgd2QqAnOsFHiXR6Vi4EPG-3qROzuvlD3ar6owxJyqOuBdoWTDb4DbcTs3NfLcb1FkGO/s320/aok.PNG" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDvnVaAZoBcmOUho1kxjboWWvMcM_VUmDdefuwZt48L_jttECaPxlDcsorBNAH6qKEGUtj6h36FcMUAhGHRVt1iE2-2auR_2l89BpAESGCPpLLfliii7Q_Eg1WFs6PLxPZoyzV/s1600/oops.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="129" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDvnVaAZoBcmOUho1kxjboWWvMcM_VUmDdefuwZt48L_jttECaPxlDcsorBNAH6qKEGUtj6h36FcMUAhGHRVt1iE2-2auR_2l89BpAESGCPpLLfliii7Q_Eg1WFs6PLxPZoyzV/s320/oops.PNG" width="320" /></a></div><div><br />
Clearly, a midpoint isn't good enough, I need something a bit more relative.</div><div><br />
</div><div>Thankfully, a simple Vector Math trick works nicely:</div><blockquote>ship.engines.angularThrust = (targetAngularVelocity - currentAngularVelocity) * strength * time;</blockquote><div>Subtracting targetAngularVelocity from currentAngularVelocity will give me a new Vector that points from currentAngularVelocity to targetAngularVelocity . Then all I need to do is shrink the strength of the vector down to a reasonable acceleration, and I'm done.</div><div><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHETnWrYTS9d8iVZdj3t464rrA_ljf4Le9LIpsEhpGbnSPlkLazWdWSu7Fvq-ycMJ4p9IZCRs7PUZOngxcZ8ZRDxCfkQHpY0GjKYapKkUGZm1pT7uylZUdpfDLPLCjy_AWgcuk/s1600/sweet.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="122" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHETnWrYTS9d8iVZdj3t464rrA_ljf4Le9LIpsEhpGbnSPlkLazWdWSu7Fvq-ycMJ4p9IZCRs7PUZOngxcZ8ZRDxCfkQHpY0GjKYapKkUGZm1pT7uylZUdpfDLPLCjy_AWgcuk/s320/sweet.PNG" width="320" /></a></div><div><br />
</div><div>And thanks to the miracles of Vector Math, this will work in any direction, under any circumstance. </div><div><br />
</div><div><br />
</div></div>Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-46848558605445683032010-11-07T01:23:00.000-07:002010-11-21T20:59:08.481-08:00Typical Day<div class="separator" style="clear: both; text-align: center;">I have a daily habit of scanning through kotaku.com and gizmodo.com. As I read through article headlines, I open the articles in new tabs for later reading. Here's a sample of what that looks like:</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYg9CVr9WEpd5aL5a5U8FTnvWIGXuPNWwn7sHYczASCKlXKUdoqRlPkcEjqQJfmXKYHci40kVe1xkNckw1dhrd0bwUCF9c-8eMcEVWp28vzmgsDoQHdBSGab9aSoKtKl49Odp4/s1600/Screen+shot+2010-10-17+at+4.12.43+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
<br />
<img border="0" height="302" img="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYg9CVr9WEpd5aL5a5U8FTnvWIGXuPNWwn7sHYczASCKlXKUdoqRlPkcEjqQJfmXKYHci40kVe1xkNckw1dhrd0bwUCF9c-8eMcEVWp28vzmgsDoQHdBSGab9aSoKtKl49Odp4/s400/Screen+shot+2010-10-17+at+4.12.43+AM.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;">I find it a good way to keep up to speed with current trends in the game and gadget industries, and also find lots of cool pictures.</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;">Sometimes I will watch a video as I read through web articles. Generally I'll watch at a TED conference or two since I find them pretty enriching. The window resizing features in Windows 7 are particularly useful here:</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy7VgDFNIw4j4zhwkzABXuPblU8JjgG9uTMG_k_zYz71NbuNoZ9qtOWHdbmg_cAQEFczHrcrHoUgW8XBbV1HoQa01Q_ECyyrGfWKzFx5bQgwKYoXpPRaNe5p7Oc5RiVH9RC9Ll/s1600/story+of+my+life.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy7VgDFNIw4j4zhwkzABXuPblU8JjgG9uTMG_k_zYz71NbuNoZ9qtOWHdbmg_cAQEFczHrcrHoUgW8XBbV1HoQa01Q_ECyyrGfWKzFx5bQgwKYoXpPRaNe5p7Oc5RiVH9RC9Ll/s320/story+of+my+life.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;"><br />
</div><div class="separator" style="clear: both; text-align: center;">Have a favorite news website to procrastinate on? Leave a comment below.</div><div class="separator" style="clear: both; text-align: center;"><br />
</div>Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-57029097788442718962010-10-27T21:53:00.000-07:002010-10-27T22:10:34.323-07:00The BridgeThis semester, I am the Technical Lead of a super-cool Science Fiction game called The Bridge.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://commandthebridge.com/"><img border="0" height="259" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM1tBKj34f6EJz5vWFa8WsQEloocoYQgoNFJpysrPgkfEiCD5XbCdJg9yQC64BDHxaESVHwv3rZ0JY9w5OoFfTBaYWZv5QK0JDyOA_PtDw1sHo9DVyrkb5XymzLXnae9AeEjuU/s320/coming-soon-title.png" width="320" /></a></div><br />
In the game, you command starship entirely with voice control.<br />
<br />
Here are some of the innovate things the game has going for it:<br />
<br />
<ul><li>Speech Recognition as a seamless part of gameplay</li>
<ul><li>The player can say things like:</li>
<ul><li>"Weapons, fire missiles at enemy ship alpha"</li>
<li>"Navigator, engage defense orbit"</li>
</ul></ul><li>Dynamic Story Engine</li>
<ul><li>Every actor in the game is an Entity</li>
<li>Entities have Relationships with other Entities</li>
<li>Relationships evolve throughout gameplay</li>
<li>Result: fully procedural storytelling</li>
</ul><li>Emotional Voice Recognition</li>
<ul><li>The player's tone is interpreted by the game</li>
<li>This affects crew loyalty towards the player</li>
</ul></ul><br><br />
<br />
Of course, that's only the beginning.<br><br><br />
<br />
For more information, check out the game's website:<br />
<a href="http://commandthebridge.com/">commandthebridge.com</a><br />
<br><br><br />
- GregGreg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-22105283205253167212010-09-17T21:22:00.000-07:002010-09-17T21:24:45.837-07:00Flash Sound Tutorial<div class="separator" style="clear: both; text-align: center;"></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: left;">I made a tutorial for using Sound Objects in Flash.</div><div style="text-align: left;"><br />
</div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR5Wbp36pydxWxNx-TkQoBhuYVk3mdEOBI33Q6Wlmrr5HVKVkVHWqqrGGWZOFrlu7nWbvEfnI_bnG-MUb0VKCm9JOaWuF2qYAlmOyEN2NbP3rH79t7ng7VwjJAIptBtFL1I4oo/s1600/Screen+shot+2010-09-17+at+9.09.02+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR5Wbp36pydxWxNx-TkQoBhuYVk3mdEOBI33Q6Wlmrr5HVKVkVHWqqrGGWZOFrlu7nWbvEfnI_bnG-MUb0VKCm9JOaWuF2qYAlmOyEN2NbP3rH79t7ng7VwjJAIptBtFL1I4oo/s320/Screen+shot+2010-09-17+at+9.09.02+PM.png" /></a></div><br />
<br />
<br />
<div>The tutorial covers a few tricks I use, including:</div><div><ul><li>Object Dictionaries</li>
<li>Creating Asset Instances in the Flash IDE</li>
<li>Importing Sound Assets</li>
<li>Creating Sound Objects in ActionScript</li>
<li>Using Sound Objects</li>
<ul><li>Play, Stop, and Change Volume</li>
</ul></ul><div>You can download the tutorial here:</div></div><div><a href="http://www.kwarp.com/downloads/2010_Sept_17_Flash_Sound.zip">Flash Sound Object Tutorial</a></div><div><br />
</div><div>The tutorial includes a Complete copy of the code, and a Skeleton copy for you to practice writing yourself. You will need Flash CS4 or later.</div><div><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/AVvXsEgZTL0aqkJb0NPO2LdJymcRBkQC3hiuZIUJJaIInZf_RmdQSk0BrW_hB9S6UZSr5oBRgYu8CbnyDh8xDcsBT3_ZETd9zs9Z2IsJrpeR7EhKFVjRZ2_gYV8f1v5Y-Xct7M1YqqEA/s1600/Screen+shot+2010-09-17+at+9.18.52+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZTL0aqkJb0NPO2LdJymcRBkQC3hiuZIUJJaIInZf_RmdQSk0BrW_hB9S6UZSr5oBRgYu8CbnyDh8xDcsBT3_ZETd9zs9Z2IsJrpeR7EhKFVjRZ2_gYV8f1v5Y-Xct7M1YqqEA/s320/Screen+shot+2010-09-17+at+9.18.52+PM.png" /></a></div><div><br />
</div><div><br />
</div><div>Surprisingly, creating a robust Sound Engine only requires about 60 lines of code.</div><div><br />
</div><div>Hope it's useful,</div><div>- Greg</div><div><br />
</div>Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-2962298552131767262010-07-08T03:33:00.000-07:002010-07-08T22:18:17.832-07:00AStar GameRecently, I learned how to implement the super-awesome pathfinding algorithm called A*. Given a start point and a goal, A* will find the shortest possible path to the goal while evaluating as few paths as necessary.<br />
<br />
<div><a href="http://www.blogger.com/"></a><span id="goog_680391971"></span><span id="goog_680391972"></span></div><div>Not satisfied with leaving such a juicy algorithm to rot in a classroom, I set out to <a href="http://kwarp.com/portfolio/astargame.html">build a game</a>.</div><div><br />
</div><div><div class="separator" style="clear: both; text-align: center;"><a href="http://kwarp.com/portfolio/astargame.html"><br />
<img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD80Zjo29AwKL87uCE0eILlJ8hQqK8uFJwgG8_9mCu6fR3adys1kLkqv5OXzaqh5IXjJBsUnMiIImR9griPVLIEo0D7LYMDZG9H-GylkPyvlpnCuqxKJq-D_yCK0OVucwYiLt0/s320/title+screen.png" width="320" /><br />
</a></div><br />
</div><div><br />
</div><div>I chose to create a Cat and Mouse game where the player tries to reach a goal while running away from evil baddies. Sound familiar? Well I've made it before:</div><div><br />
</div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdy6E3eXseuosPkUEhJFPl6DoyjNbK2nv_5QEdsG1c6Y-fabsvX3Uc6DZOrgYHdDNYDBb-jm6TBIWw_rUZa4SRz_4hZiIocmnPEYVH4aqkpDSea0AK0CFfZLmZIa55EswYwBvn/s1600/old+game.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdy6E3eXseuosPkUEhJFPl6DoyjNbK2nv_5QEdsG1c6Y-fabsvX3Uc6DZOrgYHdDNYDBb-jm6TBIWw_rUZa4SRz_4hZiIocmnPEYVH4aqkpDSea0AK0CFfZLmZIa55EswYwBvn/s320/old+game.png" width="320" /></a></div><br />
</div><div><br />
</div><div><a href="http://kwarp.com/secret/warpchase.html">Warp Chase</a> was the first videogame I ever made. And by "made", I mean copy-pasted from a game programming book and added some levels. Oh shame. At the time, I did my best to add some personal spirit to the title, but didn't know enough concepts to program any of the gameplay that I had imagined.</div><div><br />
</div><div>Lucky for me, this kind of game lends itself perfectly to A*, since baddies need to be pretty movement-efficient to chase the player effectively. I set forth to fully realize the gameplay I couldn't quite grasp before.</div><div><br />
</div><div><div class="separator" style="clear: both; text-align: center;"><br />
</div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLfUZ-L8HjpBVX6YKqFijaNXloi6MsEpwOa1TJOjG02jI4eWJIh6bijZCLgtJrSwjHOfGtUewybdS-weH-RamUBBZA0-iDVqCbThhuBig5iU7SX3E0uZRAu5TqbKcY-R4cZ_CI/s1600/astar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="142" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLfUZ-L8HjpBVX6YKqFijaNXloi6MsEpwOa1TJOjG02jI4eWJIh6bijZCLgtJrSwjHOfGtUewybdS-weH-RamUBBZA0-iDVqCbThhuBig5iU7SX3E0uZRAu5TqbKcY-R4cZ_CI/s320/astar.png" width="320" /></a><br />
<br />
</div><div><br />
</div><div>Implementing A* was an interesting exercise in itself. I spent a few days experimenting and optimizing my implementation. Ultimately, I cut my processing time for a long A* search from 117 milliseconds to under 4. The biggest gains came from two places: First, I evaluated visited nodes by looking up values in a 2D array, rather than wastefully looking through each nodes list of visited previous nodes. Second, I implemented my own priority queue using a heap, which saved a lot of time on sorting.<br />
<div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz4cT2LVUHSzvECEil1qBJ7IIhD4tQOq2ond-cfVvUoGhI0a4ilxkW1fIw8wz7KLY_qwSycbSqb2T607S-jajAmUQl9Er4H021oOFnLimRoUxD18K0rJEc0Tk2drZAnNjZtrrz/s1600/boring.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz4cT2LVUHSzvECEil1qBJ7IIhD4tQOq2ond-cfVvUoGhI0a4ilxkW1fIw8wz7KLY_qwSycbSqb2T607S-jajAmUQl9Er4H021oOFnLimRoUxD18K0rJEc0Tk2drZAnNjZtrrz/s320/boring.png" width="320" /></a></div><br />
<br />
From a gameplay standpoint, the escape mechanic was fun for a while, but I quickly grew bored of it. A* was just too intelligent to waste on such shallow gameplay.<br />
<br />
I wanted strategy.<br />
<br />
While finishing the implementation for the Escape part of the game, I stumbled upon a very interesting bug. Effectively, the bug allowed the player to create walls that could trap unsuspecting baddies. Very interesting indeed.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWv0QOOW0JiMe6qZ3g63I27gIHbNsxgEltuV4anZ-zDs1mquOGJj13zAgj6BjRKiXbhI6qAtBQasu-u9B9vkqNSIJsh7GY2-gefMPpNtYixEoOmw35wuDEtsNBg_Z0puKHRCFG/s1600/astargame+glitch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWv0QOOW0JiMe6qZ3g63I27gIHbNsxgEltuV4anZ-zDs1mquOGJj13zAgj6BjRKiXbhI6qAtBQasu-u9B9vkqNSIJsh7GY2-gefMPpNtYixEoOmw35wuDEtsNBg_Z0puKHRCFG/s320/astargame+glitch.png" width="320" /></a></div><br />
<br />
A few experiments and 9 levels later, I found that the trap mechanic allowed me to make some modestly interesting puzzles. I won't spoil the levels here though. Go play the game!<br />
<br />
<a href="http://kwarp.com/portfolio/astargame.html">http://kwarp.com/portfolio/astargame.html</a><br />
<br />
<br />
<br />
<br />
<br />
</div>Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-11384980749010064762010-03-21T00:45:00.000-07:002010-03-21T00:45:21.081-07:00Computer GraphicsHere's some cool Computer Graphics projects I've worked on this semester:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://www.kwarp.com/portfolio/lines.html"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrPHoJpf3QPiu2WigjLz-KKzZ3ATXdstGoQsTTuPxdmV526o0G266kkFWAqylmcwWmO-yCig8MIcxJgbFJkGx7RIJq204xkN1qZmfQf70gUqwA9kxgXOsBzN4-SGU-A3DRsIFm/s320/lines_screen.png" /></a></div><div style="text-align: center;">(<a href="http://www.kwarp.com/portfolio/lines.html">Download Here</a>)</div><br />
In this assignment I wrote a variant of the Midpoint Algorithm to draw lines. You can also toggle attributes such as color, anti-aliasing, and line weight.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://www.kwarp.com/portfolio/lines.html"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtWwdS9qCAJbAGSh9uKJV1eAWdkm6evyuV4oRdf_3NDgQWc4ltKn2q5RVlNSiZwSddy3octXpRyjd-y1RlmVHMTmGZzKzcalycPpSYM-BySbs8mUETuSeYlxvdMf7e7dUFZmd1/s320/wires_screen.png" /></a></div><div style="text-align: center;">(<a href="http://www.kwarp.com/portfolio/wires.html">Download Here</a>)</div><br />
Here's a cool Wireframe renderer. I wrote Matricies that handle all the transforms from Object Space to Screen Space, and everything in between. I threw in my animated robot dude for good fun, and a slider that moves between a pure perspective and orthographic projection. With a perspective projection, objects farther away seem smaller and converge at a vanishing point. On the other hand, orthographic projection has no vanishing point at all.<br />
<br />
I wrote the programs using a Java-based work environment called <a href="http://www.processing.org/">Processing</a>. It's very easy to get started making cool stuff. Check it out.Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com1tag:blogger.com,1999:blog-23809115.post-58907920497580371002010-01-18T14:40:00.000-08:002010-01-22T12:39:33.598-08:00The Factory ProjectLast semester, I took a Computer Science course about concurrent programming using the Agents. For my final project, I was put into an eleven-person programming team and tasked to design a way for robots to assemble kits in a Factory in 6 weeks. I have put together a walkthrough video of our results:<br />
<br />
<object width="450" height="263"><param name="movie" value="http://www.youtube.com/v/f6XuUCLgIkI&hl=en_US&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/f6XuUCLgIkI&hl=en_US&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="450" height="263"></embed></object><br />
<br />
The five of us in my CSCI 201 class worked on the system design and backend. The other six people were in CSCI 200 class and coded the GUI components.<br />
<br />
Our team was very strong, and chose to go well beyond the requirements for the assignment. We chose to make both the machines and the intelligence (making decisions for the machines) operate on separate threads, accurately simulating how a real factory would behave. There are approximately 43 threads in this program.<br />
<br />
I decided to try pair-programming with one of my team mates on this project, which turned out to be the best idea ever. We designed pseudo-code for key parts of the system in a single night, and comprehensively worked through the code on paper (and an excel spreadsheet) to insure that the logic worked out. From there, coding was trivial.<br />
<br />
The most difficult part of the project for me was designing the behavior for the Factory's FeederController. During runtime, the FeederController cycles through four major part-feeding states. At any time during any of those states, the Feeder could be interrupted with a command to feed a new type of part (or parts). The challenge was designing a system intelligent enough to appropriately respond to new commands under any circumstance.<br />
<br />
Unit Testing was an unexpectedly lengthy ordeal, eating up a couple days of my life and 1700 lines of virtual paper. In hindsight, such a comprehensive Unit Test was absolutely necessary. I discovered several behavior-breaking bugs that would have been impossible to detect after integration with the rest of the team. In fact, after integration, my tested components of the system worked almost exactly as expected, and suffered significantly fewer problems than the horror stories I heard from other teams in the class.<br />
<br />
While the resulting Factory simulation doesn't look as cool or flashy as the games on my website, it was a worthwhile team experience that dealt with some very difficult programming designs. Additionally, the tools I gained experience with, Subversion, Team Wikis, and Unit Testing, will be indispensable on future programming projects.Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com2tag:blogger.com,1999:blog-23809115.post-24762921019772643912010-01-10T00:58:00.000-08:002010-01-10T01:03:02.893-08:003D Animation ReelDuring the Fall 2009 semester, I took a 3D animation course that let me dabble in modeling, texturing, animating, and lighting 3D objects. I've put together a quick reel of some of the more interesting stuff I worked on.<br />
<br />
<object height="263" width="450"><param name="movie" value="http://www.youtube.com/v/pSxmzFoQpI4&hl=en_US&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/pSxmzFoQpI4&hl=en_US&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="450" height="263"></embed></object><br />
<br />
The two big subjects the course introduced me to were animation and lighting. I really enjoyed animating in Maya; it breathed some much-needed life into my (otherwise static) creations. The lighting process is sort of a mixed bag. My 3D objects looked absolutely stunning when lit correctly, but the actual process of lighting an object well took a lot of practice and patience.<br />
<br />
Overall, I learned some powerful techniques in this animation course that will serve me well in future 3D game projects.Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-14957731626698043382009-12-11T01:19:00.000-08:002014-07-14T01:37:41.503-07:00Instead of Writing a Research Paper, I Made A Game<div class="separator" style="clear: both; text-align: center;">
<a href="http://kwarp.com/projects/youaregodzilla.html"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi57jAndps-K7u4IlUKrRQS-SfLDVC-TiCnNK3J3YFTIZio75q3_ft2Gs3ZRPndiGfdir2wWBO7hHZtuezPfawwQb_hm_mi8F3z25QpT0MeMX27WjMJQ9zOZnN5vV1HWiIDrZvN/s320/title.png" /></a></div>
<div style="text-align: center;">
<br /></div>
<br />
<div>
This semester, I took a General Education class on Modern Japanese Literature. One of the cornerstones of the course was writing a lengthy research paper about one of the topics discussed in class. Happy to push my luck, I proposed to the professor that I build a game instead of writing a paper. I figured that creating a simple game to satisfy the assignment would only take a few days to make, and it would give me an excuse to work with Antonio Cade, a fellow classmate taking the course, and an excellent artist.<br />
<br />
Our professor was intrigued with the idea, but only let us go ahead with it the project if we still wrote a 5-page paper to turn in with the game. Not too bad. That makes about 2.5 pages for each of us, and I could easily fill that space with discourse about the game design process. In fact, that's exactly what I did.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIaAEbaxyRUVglCiIVbaYKUscimg6oR2x2ueqLTLubc1kg1WH34WkGtTtqnXeNBu0wkyDQKGrm4L-Bu8kJuZ4FgwvKrYRv8GP_4Iz5unm6I9gNB1EWiGwcHLWnF1E2-xBv0E5y/s1600-h/screen1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIaAEbaxyRUVglCiIVbaYKUscimg6oR2x2ueqLTLubc1kg1WH34WkGtTtqnXeNBu0wkyDQKGrm4L-Bu8kJuZ4FgwvKrYRv8GP_4Iz5unm6I9gNB1EWiGwcHLWnF1E2-xBv0E5y/s320/screen1.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
Play the game here: <a href="http://kwarp.com/portfolio/youaregodzilla.html">http://kwarp.com/portfolio/youaregodzilla.html</a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The game is pretty open-ended. You play as Godzilla, and can walk anywhere on the map. Beware that everything you walk into crumbles beneath your mighty feet. There are two ways to "win" the game. Either violently destroy all the buildings, or disappear into the ocean, never to be seen again. The point of the game is to reveal what the players think Godzilla should think and do. In actuality, understanding what Godzilla is about is a pretty sophisticated topic. The paper portion of the assignment discusses those issues in depth.</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;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoVKp1qSFJZh4pSXQUIP4Z4Fwi98xrnK4SAt79F8p6IIrMPDKs9pL3bL1pM1R53NbYbmMQTGzRr63ERhmiGeg-Tr79HltMY02p_u0c-eRZsu8e7DvDxRhd_Envs__u4untzPqu/s1600-h/screen2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoVKp1qSFJZh4pSXQUIP4Z4Fwi98xrnK4SAt79F8p6IIrMPDKs9pL3bL1pM1R53NbYbmMQTGzRr63ERhmiGeg-Tr79HltMY02p_u0c-eRZsu8e7DvDxRhd_Envs__u4untzPqu/s320/screen2.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Antonio ended up writing the more "researchy" portion of the paper, while I wrote about the game design and vision. Frankly, writing about the game design process was one of the most fun things I have ever done in a writing course. The paper occupies the rest of this blog post. See if you can find where I stopped writing and Antonio began. ;)</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<a name='more'></a><br />
<br />
<div class="separator" style="clear: both; text-align: left;">
===========================================</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div align="right" class="MsoNormal" style="text-align: right;">
Greg Lieberman</div>
<div align="right" class="MsoNormal" style="text-align: right;">
Antonio Cade</div>
<div align="right" class="MsoNormal" style="text-align: right;">
ARLT 100g</div>
<div class="MsoNormal">
<br /></div>
<div align="center" class="MsoNormal" style="text-align: center;">
Designing the Game “You Are Godzilla”</div>
<div align="center" class="MsoNormal" style="text-align: center;">
<br /></div>
<div class="MsoNormal" style="line-height: 200%; text-indent: 0.5in;">
We (Antonio and Greg) initially had drastically different ideas for how to approach designing a game that answers the question “What is Godzilla Really About?”. </div>
<div class="MsoNormal" style="line-height: 200%; text-indent: 0.5in;">
Greg initially wanted to design a narrative-driven game whose theme was to destroy Godzilla before he destroys you. The player would take the role of a person living in a city that Godzilla had begun to destroy, and encounter several moral choices in the game that ultimately lead to either destroying Godzilla or being destroyed by Godzilla. For example, in one scene Greg imagined the player jumping across building rooftops to run away from Godzilla as the creature mindlessly raged forward. If the player kept running away, Godzilla would eventually destroy the whole city. If the player failed to run away, Godzilla would kill the player and then destroy the city. However, if the player strategically attacked Godzilla, the player would defeat Godzilla and the city would be saved. </div>
<div class="MsoNormal" style="line-height: 200%; text-indent: 0.5in;">
Greg’s game design was an interesting approach to exploring the way that humans react to Godzilla’s presence, but the design itself did not attempt any deep introspection into understanding Godzilla. In fact, it did the opposite. Greg defined Godzilla as an aggressive villain in the game that must be destroyed for the common good of mankind. Thus, all of the player’s moral choices in the game were framed within the boundaries of Godzilla as a devastating enemy. Ultimately, this one-sided view of Godzilla led to the rejection of Greg’s game design.</div>
<div class="MsoNormal" style="line-height: 200%;">
Antonio proposed an open-ended exploration game where the player controlled Godzilla directly, allowing the player to explore several of Godzilla’s actions and consequences. The player begins the game as Godzilla near the coast of a city. From there, the player could choose to violently attack the city, attack nearby battleships, harmlessly sulk in the ocean, or leave the map entirely. The genius of this game design is that it empowers the player to be the agent of moral choice, and to project the player’s ideas of what Godzilla does into actions in the game. In tackling the question of “What is Godzilla Really About?”, the game reveals the intentions and biases of the player.</div>
<div class="MsoNormal" style="line-height: 200%; text-indent: 0.5in;">
Wherever Godzilla walks on the game map, the creature leaves a path of destruction in its wake. In our Godzilla game, Godzilla will destroy buildings as it walks past them, even if it is not shooting fireballs. This was a crucial design choice. As Honda Ishiro once observed, “Monsters are tragic beings. They are not evil by choice; they are born too tall, too strong, too heavy… They do not attack humanity intentionally, but because of their size they cause damage and suffering” (Ryfle, 161). Ishiro’s comments highlight an interesting ambiguity. Godzilla is not intrinsically a menacing, destructive force bent on destroying human civilization. Rather, it is completely possible that the only reason Godzilla would approach a metropolis is to explore and satisfy its primitive curiosity. The intention itself seems innocent to Godzilla, but a grave problem to the humans it encounters. We saw this curiosity manifest itself in many of the students who play-tested the game. Upon first playing the game and viewing the city, many students curiously walked into the city and began destroying buildings, even if violent destruction was not their intention.</div>
<div class="MsoNormal" style="line-height: 200%; text-indent: 0.5in;">
The fact that no part of the game map actively tries to stop Godzilla is meant to follow a common theme present throughout all of the movies, “the profound vulnerability of Japan” (Tsutsui, 91). When a player controls Godzilla, buildings crumble, trees snap, and battleships helplessly sink. The message here echoes that of the movies, “we certainly can’t count on the Japanese government, the United Nations, the scientific community, big business, the professional class, or even the world’s armies to do a very good job of protecting life, limb, and property” (Tsutsui, 91). The world’s utter failure to stop Godzilla further accentuates how out-of-control this “child of the atomic bomb” has become. Here is this huge creature, a product of the reckless hubris of civilization, able to easily stomp all over civilization without resistance. The clear lack of ability to stop Godzilla also expresses the loss of faith in science and government held by Japanese society since American occupation.</div>
<div class="MsoNormal" style="line-height: 200%; text-indent: 0.5in;">
The production of Godzilla was taken very seriously, as the film was cultural reminder of Japan’s suffering during the Atomic Age and the dangers of technology. Barely a decade after the atomic bombings of Hiroshima and Nagasaki, the effect of nuclear warfare was still fresh in the memory of Japan’s population. The culture as a whole came to recognize the deadly potential that belies nuclear technology, a strong theme of the Godzilla series. In March 1954, a Japanese fishing vessel, Lucky Dragon No. 5, strayed into a U.S. testing area for hydrogen bombs near Bikini Atoll. One crew member died, another 23 were contaminated from the massive amounts of radiation, and some of the irradiated fish even made its way into the Japanese market. This event serves to show the unexpected and dangerous repercussions of nuclear testing, and its indiscriminance towards the lives of innocents. Godzilla brings these tragic events into public awareness through clear thematic reference, as shown in the opening scene of the 1954 Godzilla film: a fishing vessel is suddenly obliterated by a mysterious energy blast from under the sea. The conscious decision to feature national disasters as plot points shows the director’s intention to openly discuss the impact of these events, and to force the audience to critically analyze their significance in Japanese culture. Japan already suffers from natural disasters such as earthquakes, tsunamis, and typhoons, and by this time the appearance of nuclear testing has instilled another fear of massive destruction in the heart of its culture.</div>
<div class="MsoNormal" style="line-height: 200%; text-indent: 0.5in;">
Godzilla truly is a monstrous creature of destructive nature, but his true intentions and feelings remain a mystery to this day, making his identity as a character quite ambiguous. Godzilla’s potential for destruction is constantly made evident, whether he is trampling through skyscrapers and terrorizing the populace, or battling fierce monsters of equal or greater size. However, his use of his sheer size and power has shifted throughout the life of the series. Sometimes he is a traditional giant monster, mindlessly bent on decimating anything and everything in his path, as illustrated in our game by the option to destroy a large number of buildings, battleships and trees. At other times he is the defender of Japan, protecting it from hostile creatures like Rodan or Mothra in gigantic battles. He is a symbol of both the potential hope and the destruction brought by technological advancement, although nearly every instance of hostility in the series—the monsters themselves—is created by the side-effects of nuclear testing, most often radiation. His entire series plays on faults of mankind that could possible lead to its destruction: the greed for power, the desire for dominion over nature instead of living in harmony with it, the will to destroy anything we cannot understand or control.</div>
<div class="MsoNormal" style="line-height: 200%; text-indent: 0.5in;">
The article "Japan & Godzilla: Reflecting a Nation's Fears, Concerns and Culture” quotes an excellent summary of Godzilla’s identity as the “reverse of every Japanese stereotype. He is huge, in a country where, until recently, people were relatively small. He is clumsy and rude in a country where people tend to be graceful and polite. He is spontaneous in a place that values the impassive, studied response. He is confrontational where conciliation is considered proper behavior. He is, in essence, a nuclear bomb in a country that is emphatically opposed to nuclear weapons" (Easton, 2). Godzilla is Japanese cultural icon representing the many issues of nuclear warfare and its negative, unpredictable effects on humankind, but as a character he forms a duality with the values and characteristics that make Japanese culture unique. In this respect he is almost an anti-hero to the Japanese people and their values; he is not a character one can remotely relate to, and he often acts in opposition to scientific progress and political authority. He lays waste to industrialized areas with tall buildings and communication towers like a child trampling through a sand castle, and even demolishes the Japanese parliament building. His actions stress the vulnerability of civilization’s building blocks in situations of crisis, yet at the same time he defends it from other his hostile entities. Considering these characteristics as a benefactor and as a destroyer, Godzilla stands as a symbol of restraint against dangerous scientific progress. Technology, while yielding the tools such as medicine and transportation which make human life safer and more convenient, gives birth to indiscriminant, destructive tools such as the atomic bomb. Godzilla is a testament against the creation and use of such technology, as his own destructive nature parallels the destructive potential of man’s own tools.</div>
<div class="MsoNormal" style="line-height: 200%; text-indent: 0.5in;">
<br /></div>
<span style="font-family: Cambria; font-size: 12pt; line-height: 200%;"><br clear="ALL" style="page-break-before: always;" /> </span> <br />
<div class="MsoNormal" style="line-height: 200%; text-indent: 0.5in;">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-size: 24pt;">Work Cited<o:p></o:p></span></div>
<div class="MsoNormal">
Ryfle, <u>Japan’s Favorite Mon-Star</u>. Chicago: LPC, 1998.</div>
<div class="MsoNormal">
Tsutsui, William. <u>Godzilla on My Mind.</u> Palgrave McMillan, 2004.</div>
<div class="MsoNormal">
Gunde, Richard. "Godzilla and Postwar Japan." (2005): n. pag. Web. 8 Dec 2009. <http: article.asp="" parentid="24850" www.international.ucla.edu="">.</http:></div>
<div class="MsoNormal">
Bunchwacky, . "Japan & Godzilla: Reflecting a Nation's Fears, Concerns and Culture." (2008): n. pag. Web. 10 Dec 2009. <http: 676765="" article="" cat="40" japan_godzilla_reflecting_a_nations.html="" www.associatedcontent.com="">.</http:></div>
<br />
<br /></div>
Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-55377102401878819362009-12-10T18:20:00.000-08:002009-12-11T17:19:56.744-08:00Semester in Review: FA 102I took a Fine Arts Design course this semester to contribute to my minor in 2D Art For Games. The course had me do a lot of sketching and painting with a solid watercolor paint called Gouache. The stuff was slick, better than printer ink.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOgVIpy_tmmaDXj9ciZF0kPcaBukWrSbfmCYkW_JRnvHkVxYo5eI7OOvcao-vLfZQWuWGQXY8K9Lkf__j11IpxpxjL7BW9f0WJZB3yA_t82mdE_dzmbVjzh2t6C6Jaurdvy9_i/s1600-h/IMG_6788.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOgVIpy_tmmaDXj9ciZF0kPcaBukWrSbfmCYkW_JRnvHkVxYo5eI7OOvcao-vLfZQWuWGQXY8K9Lkf__j11IpxpxjL7BW9f0WJZB3yA_t82mdE_dzmbVjzh2t6C6Jaurdvy9_i/s400/IMG_6788.jpg" /></a><br />
</div><br />
These pieces are created by painting two sheets of bristol paper with black and white paint. The shapes are then cut out of one sheet and glued onto the other. The result is crisp, clean, and delicious.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAUme_U3ItJ3wnYPvbgNIQFEtSDULAbZfpuF64p6u5aH9rwp1-BMXhDNsazcCEeKaMDwYgPT_0UBlk-fHY6Uc2XDhhDFxWk3cD00_KS0txMjSDTPvdzlUOtsfnDrBjZxnnpmrA/s1600-h/IMG_6714.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAUme_U3ItJ3wnYPvbgNIQFEtSDULAbZfpuF64p6u5aH9rwp1-BMXhDNsazcCEeKaMDwYgPT_0UBlk-fHY6Uc2XDhhDFxWk3cD00_KS0txMjSDTPvdzlUOtsfnDrBjZxnnpmrA/s400/IMG_6714.jpg" /></a><br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyRnkWTip-j0lr6CUYuSMGJO9J9zGe_umLmMhmwIzytZHKl8vURua6UVDW38lWTeg9csquKFYM_ffTYW5AOymf3Ue20e34vZGVvjWp2bKMPliPW2UfyLTp2z0bGnDYlmou9i0H/s1600-h/IMG_0052.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyRnkWTip-j0lr6CUYuSMGJO9J9zGe_umLmMhmwIzytZHKl8vURua6UVDW38lWTeg9csquKFYM_ffTYW5AOymf3Ue20e34vZGVvjWp2bKMPliPW2UfyLTp2z0bGnDYlmou9i0H/s400/IMG_0052.jpg" /></a><br />
<div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;">The course put a huge emphasis on the process of drafting art. All of our assignments began with several pencil thumbnails, the best of which became ink drawings, then full size drawings, and ultimately a final painted product.<br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE_m8sl-cuAeFRpWMKi4tf_7wKQncQ9Qc1PK3SVweqxDJBhG0tId4pGsK-8cUaRkduiChl6GkoMjjGK5IY1wT2kv_D8wIdoswFL9xtGX2UMB03hvatYUruM3D1Nr198Q81f5uh/s1600-h/IMG_6827.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE_m8sl-cuAeFRpWMKi4tf_7wKQncQ9Qc1PK3SVweqxDJBhG0tId4pGsK-8cUaRkduiChl6GkoMjjGK5IY1wT2kv_D8wIdoswFL9xtGX2UMB03hvatYUruM3D1Nr198Q81f5uh/s320/IMG_6827.jpg" /></a><br />
<div class="separator" style="clear: both; text-align: center;"><br />
</div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFA385cpgCrRPZKUdXf_TNjBwQsxx9rmjFArzIEIdDuLOWQZ40lDi4R31NLxA4DbgGQoNEcyxafxzr-USmqaiwCBD-Da_BL1mvHbhi7OftkzES6sh7_igd12s8pqwFkxSV8EvN/s1600-h/IMG_6829.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFA385cpgCrRPZKUdXf_TNjBwQsxx9rmjFArzIEIdDuLOWQZ40lDi4R31NLxA4DbgGQoNEcyxafxzr-USmqaiwCBD-Da_BL1mvHbhi7OftkzES6sh7_igd12s8pqwFkxSV8EvN/s320/IMG_6829.jpg" /></a><br />
<br />
We also had our fair share of technical painting exercises. I will never look at gray the same way again.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzl_e0sGF9JPuJn7jvHPfvHHz9f_NmYc8MxF_nXRMqZ6PIRZm2z44MDTGsd2YfW5MZqMkOg8L29sGqElszlySVEDn7l7Rq5QmFVmmEp1Sk34g6x248OV6wEn0ABkxPBMi1QdIw/s1600-h/IMG_0069.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzl_e0sGF9JPuJn7jvHPfvHHz9f_NmYc8MxF_nXRMqZ6PIRZm2z44MDTGsd2YfW5MZqMkOg8L29sGqElszlySVEDn7l7Rq5QmFVmmEp1Sk34g6x248OV6wEn0ABkxPBMi1QdIw/s320/IMG_0069.jpg" /></a><br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPd1DqyVX2giuSxRedke0DMid5TkVHNJdMs4t8fFRMFoOdMOG2ZSVld9Ndj_ZbUn7DLtVJlznYQpln2JT4dqIW9hXu4V3_9pAaj89z9vOZREignYg69fY98LRitnkWvzur9Mvl/s1600-h/IMG_0070.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPd1DqyVX2giuSxRedke0DMid5TkVHNJdMs4t8fFRMFoOdMOG2ZSVld9Ndj_ZbUn7DLtVJlznYQpln2JT4dqIW9hXu4V3_9pAaj89z9vOZREignYg69fY98LRitnkWvzur9Mvl/s1600-h/IMG_0070.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPd1DqyVX2giuSxRedke0DMid5TkVHNJdMs4t8fFRMFoOdMOG2ZSVld9Ndj_ZbUn7DLtVJlznYQpln2JT4dqIW9hXu4V3_9pAaj89z9vOZREignYg69fY98LRitnkWvzur9Mvl/s320/IMG_0070.jpg" /></a><br />
</div><br />
<div class="separator" style="clear: both; margin: 0px; text-align: center;"><br />
</div><div class="separator" style="clear: both; margin: 0px; text-align: center;">My only frustration with the course was that I could not submit any of my final drafts as a computer image (not even printed). The final piece needed to be assembled by hand.<br />
</div><div class="separator" style="clear: both; margin: 0px; text-align: center;"><br />
</div><div class="separator" style="clear: both; margin: 0px; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8XbEt79phANB9k2fKjDkHWGlX7s5dnZvUb4IP7HIK2qd09Gzpn12p31D-HDLcdGaFIBINCt2i15fGz8bAUrK8ePRz_QklT-IHlWWsTewWBKCvam8bwMp68CIzjcXRBQt50o6T/s1600-h/shootforthestars4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8XbEt79phANB9k2fKjDkHWGlX7s5dnZvUb4IP7HIK2qd09Gzpn12p31D-HDLcdGaFIBINCt2i15fGz8bAUrK8ePRz_QklT-IHlWWsTewWBKCvam8bwMp68CIzjcXRBQt50o6T/s320/shootforthestars4.jpg" /></a><br />
</div><div><br />
</div><div style="text-align: center;">Of course, that didn't stop me from coloring my sketches in Photoshop to determine color schemes. :)<br />
</div><br />
<div style="text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIhH6ajdWDznWK4AbI43kWPiVVNmmHJ4P_2oHtglDNui4hQq-_BL5HPNgH9Ln-sxcADWPZTNqNxv2gGn94ZbJyP50dSfScxFx0C_2PZxbBH-DwOwv5Djreap8cs6kmMf91_BfI/s1600-h/IMG_7030.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIhH6ajdWDznWK4AbI43kWPiVVNmmHJ4P_2oHtglDNui4hQq-_BL5HPNgH9Ln-sxcADWPZTNqNxv2gGn94ZbJyP50dSfScxFx0C_2PZxbBH-DwOwv5Djreap8cs6kmMf91_BfI/s320/IMG_7030.jpg" /></a><br />
</div><br />
<div style="text-align: center;">The final product, a 14 by 17 inch poster.<br />
</div><div style="text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOji5E9KzRLh28jj6srpuXFfv0W6aDb4y68_D8cTT0ky3GbAY-TYms8oZM-2qIZ0F6Mrgp0Lqsa-v2vLesM7P8C4HH3Posy3MMwQxvQenvutVcRvwIqIF32MeIHt6R5JfRg7FZ/s1600-h/8BP079.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOji5E9KzRLh28jj6srpuXFfv0W6aDb4y68_D8cTT0ky3GbAY-TYms8oZM-2qIZ0F6Mrgp0Lqsa-v2vLesM7P8C4HH3Posy3MMwQxvQenvutVcRvwIqIF32MeIHt6R5JfRg7FZ/s320/8BP079.gif" /></a><br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;">The last class assignment was to redesign a CD album cover. I chose one of my favorite indie composers.<br />
</div><div style="text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBP8hQfoiFy4Bj_uDAvioGxJF-1oGtnLj4BgJOwD_lu7m79re1tXZMDrQB9WxAbZoz7sD946-hnYNs7VKBt1dNHXD6K2ExyNoBLUVcwvrapIW0dZfLd0NV7DWqrHmRBiLZo7Vw/s1600-h/IMG_7022.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg189_8i7JlR0wJK3xd7VlplAXCijS04OAUFaKOv_fAyUZWtvbGe7JgY11NVJr6cqV1p0jwuEmGTadFH2GIhCkfyQEASd8aqKMF-rbR0g-UKZdcWojWykYjerh3osvFrib3BHwg/s1600-h/IMG_7032.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijigFSkLLZo72K_4eJoesAadlLIH1qwjjiWAKMT6vSzvuVEy-V_EqdinaoyOD2C9RfPXmYau1CDJCUkgzyPYGTwDwrQQBxhrwGfTinqGn-BlFcXD_qFXMavpX-G1-iP07X5ECA/s1600-h/IMG_7032.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijigFSkLLZo72K_4eJoesAadlLIH1qwjjiWAKMT6vSzvuVEy-V_EqdinaoyOD2C9RfPXmYau1CDJCUkgzyPYGTwDwrQQBxhrwGfTinqGn-BlFcXD_qFXMavpX-G1-iP07X5ECA/s320/IMG_7032.jpg" /></a><br />
</div><div style="text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;">I liked the pattern in the original cover, and decided to expand upon it with imagery that the music triggered in my mind. To keep in line with the technically raw nature of the music, I repeated the simple primary colors and strong angular lines found in the pattern. Materials used were colored pencil, and drops of paint for the stars.<br />
</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;">Overall, this art class gave me great practice in design and composition. I learned some useful skills for designing color schemes that will be essential for my digital art projects.<br />
</div>Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0tag:blogger.com,1999:blog-23809115.post-72995143800304409512009-10-21T18:04:00.000-07:002010-04-12T23:20:06.741-07:00Designing Levels for Kory The Thief<div class="separator" style="clear: both; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJfmuU-jRLCJIAQLpnaG8R0D2wnl7PBURzd4oaciFoH8pXLFP8dsB_7TkKLOBj-W57qiCBEN_o_IIMQf1hJpDQzZVfp_Pfq6qp_puzhc9MKNWDxhW-0pTkjhl0bZEan26Mmv-E/s1600-h/ktt_screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJfmuU-jRLCJIAQLpnaG8R0D2wnl7PBURzd4oaciFoH8pXLFP8dsB_7TkKLOBj-W57qiCBEN_o_IIMQf1hJpDQzZVfp_Pfq6qp_puzhc9MKNWDxhW-0pTkjhl0bZEan26Mmv-E/s400/ktt_screenshot.png" /></a></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><a href="http://kwarp.com/portfolio/korythethief.html">Kory The Thief</a> was an interesting exercise in level design. Thanks to the Edward Flash Platformer Engine, I was able to build sophisticated levels with relative ease the Flash IDE. In this post I will describe the my intentions when designing the levels, and why every piece has its place.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK5OFLLDSEk0UHPRUgZUhFNhgqo1EG4rhM-_oFo0060Un9t3N-ynZyBkRZQdAI6w_ivSB8mQSVTfb4y-FYQgzRNTsXOPZbPncfeDoxp4mgLmRUBhecLn3_18c8GQBK07peB3d0/s1600-h/korythethief0.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5395370264255580690" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK5OFLLDSEk0UHPRUgZUhFNhgqo1EG4rhM-_oFo0060Un9t3N-ynZyBkRZQdAI6w_ivSB8mQSVTfb4y-FYQgzRNTsXOPZbPncfeDoxp4mgLmRUBhecLn3_18c8GQBK07peB3d0/s400/korythethief0.png" style="cursor: pointer; display: block; height: 82px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Tutorial Level</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">The purpose of the tutorial level is to introduce the player to the key elements of the game. One at a time the player learns to move, jump over obstacles, the nature of sloped surfaces, the consequences of touching lasers, and the behavior of fans and trampolines. Upon completing the tutorial level, the player is familiar with every element that commonly appears throughout the game's levels.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjc8piLlJ2MPBGxhb0x5749MIrRQRUvbj-CGYGCC4ocsvkU_Ce5YeAYs4fd5WBpL3NOrIcuLmoG3o4IiCaxRphtquoj1U1JMH1C48fhsHevLBUgRpmr0MGtzqzwlTG_bm28XTrJ/s1600-h/korythethief1.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5395370269243980626" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjc8piLlJ2MPBGxhb0x5749MIrRQRUvbj-CGYGCC4ocsvkU_Ce5YeAYs4fd5WBpL3NOrIcuLmoG3o4IiCaxRphtquoj1U1JMH1C48fhsHevLBUgRpmr0MGtzqzwlTG_bm28XTrJ/s400/korythethief1.png" style="cursor: pointer; display: block; height: 172px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Dino Level 1</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">To complete a level in Kory The Thief, the player must first grab the level's jewel, then proceed to the door. Level 1 presents the jewel in plain sight, making the goal clear. However, the player needs to circle around the entire level to grab it. In this process the player will likely see the door and find it inactive. After grabbing the jewel, the player has no hint of where to go except to the door. Thus the requirements for level progression are learned.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTJy_po9QsKt0A9JtVr_jU-doZc0NbOohKqYwOUuFuZ_O-F7lmbAoxyMzf_j7vTSdDkccylHvnOsBcwgPmeENphbdc3WQ6lXX2CAM11YuMGaG63v6XrHOWhSjYJyP41txLNDXX/s1600-h/korythethief2.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5395370273398532418" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTJy_po9QsKt0A9JtVr_jU-doZc0NbOohKqYwOUuFuZ_O-F7lmbAoxyMzf_j7vTSdDkccylHvnOsBcwgPmeENphbdc3WQ6lXX2CAM11YuMGaG63v6XrHOWhSjYJyP41txLNDXX/s400/korythethief2.png" style="cursor: pointer; display: block; height: 400px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 241px;" /></a></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Dino Level 2</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">This level lets the player get some air time with fans and trampolines. It adds a welcome change of pace compared to the previous two levels. Like the previous level, the jewel is in an easy-to-see but hard-to-reach location. Moving laser beams are also introduced, increasing the play difficulty a bit.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid7FD8-inY_kFwnK8IVMa6_JO76s3mZa7WrrywduaucTnJeN-QvW8b6rGfK1RixBjL_LcJQEThe3ciOi6FOpuphpnrnwW_tI7AzN9iIVzQhewwV1uy6QMbnIHejpVH1Tvzk586/s1600-h/korythethief3.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5395370654551780898" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid7FD8-inY_kFwnK8IVMa6_JO76s3mZa7WrrywduaucTnJeN-QvW8b6rGfK1RixBjL_LcJQEThe3ciOi6FOpuphpnrnwW_tI7AzN9iIVzQhewwV1uy6QMbnIHejpVH1Tvzk586/s400/korythethief3.png" style="cursor: pointer; display: block; height: 253px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Dino Level 3</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Naturally, a dinosaur themed set of levels should have a giant dinosaur skeleton. The player is pretty smart at this point, so I set a few simple laser traps. They can be easily avoided through caution or trial and error.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCiy95e6IyTZaI0nB4uR6gvoaYSdXMb_ONoM960LrCHK-dd4ZAYDycjGpZB7zR-XKGOTUoRaZDD8RCwJw88RUGRvqu3pXD0yar8jLrtKGhFtu53ug-gcgbUxETLKHCFeOR_Y4w/s1600-h/korythethief4.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5395370663137887058" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCiy95e6IyTZaI0nB4uR6gvoaYSdXMb_ONoM960LrCHK-dd4ZAYDycjGpZB7zR-XKGOTUoRaZDD8RCwJw88RUGRvqu3pXD0yar8jLrtKGhFtu53ug-gcgbUxETLKHCFeOR_Y4w/s400/korythethief4.png" style="cursor: pointer; display: block; height: 185px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Aqua Level 1</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">A new environment theme. By this point, the player knows to get the jewel then proceed to the door, so the jewel is not in plain sight like previous levels.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcMV9uLu_XoCJSEZ4HIMmvq1ACI9pU3oHtXwFR1KbMfehxSoAKR7_rxZyaWlx8IVTH3s02XkSYxDAbtNulVkOWNlcx3v9blLxCO5Y0vxSrzTKJEq65QhUQR0M6nbAjpn7-HkMT/s1600-h/korythethief5.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5395370672638356994" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcMV9uLu_XoCJSEZ4HIMmvq1ACI9pU3oHtXwFR1KbMfehxSoAKR7_rxZyaWlx8IVTH3s02XkSYxDAbtNulVkOWNlcx3v9blLxCO5Y0vxSrzTKJEq65QhUQR0M6nbAjpn7-HkMT/s400/korythethief5.png" style="cursor: pointer; display: block; height: 131px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Aqua Level 2</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">The difficulty ramps up a bit here, requiring synchronized jumping with the motion of the lasers. I am particularly happy with how the 3 lasers at the end of the level almost squeeze the player into getting caught. Once the player gets to the door, well, mind the gap.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglqwxsnFzw4iAls452i1lPCXeXzkdoTnTvId_NNYWY654b083npeJHBHWzdWdljwDqcrZkTugAnUXFLzamDjxhksQk8on64-w-WJBcso2CSfDZT6_sT3X1WC0tJtvdV-zDtV7I/s1600-h/korythethief6.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5395371260833028818" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglqwxsnFzw4iAls452i1lPCXeXzkdoTnTvId_NNYWY654b083npeJHBHWzdWdljwDqcrZkTugAnUXFLzamDjxhksQk8on64-w-WJBcso2CSfDZT6_sT3X1WC0tJtvdV-zDtV7I/s400/korythethief6.png" style="cursor: pointer; display: block; height: 400px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 279px;" /></a></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Aqua Level 3</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">This stage breaks from the theme of dodging lasers to solving a simple, but tricky puzzle. When the player jumps from a high enough height into the fan updraft, the player will fall past the updraft, hit the trampoline, and shoot up to the ceiling where the jewel is.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi4-4QzwmyqsJ4RnxI9ysMO8iXMIiYAGNzWZ0Ed-zbONEfHUpRrllgopDwQph466gh7L6jm0b2KlsnaNSNPMjk_ZKrnyPnWNOrkAO3AJFBoTXTTY6k5bXi7A7ZMOKYI3_i1Tig/s1600-h/korythethief7.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5395371269536215282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi4-4QzwmyqsJ4RnxI9ysMO8iXMIiYAGNzWZ0Ed-zbONEfHUpRrllgopDwQph466gh7L6jm0b2KlsnaNSNPMjk_ZKrnyPnWNOrkAO3AJFBoTXTTY6k5bXi7A7ZMOKYI3_i1Tig/s400/korythethief7.png" style="cursor: pointer; display: block; height: 193px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Egypt Level 1</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">This stage introduces conveyor belts and some tough lasers to dodge. The player is smart enough at this point to navigate stages without guidance, so I placed an impassable laser path between the jewel and the door to throw the player off.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLsCTyDygRhHEVu4EuYyMH4U46K1iRU_SekhsM0RRZjaHl7eSy6_RQyI5SBYpZ8hJVODkzxvyWGa_aEuydX5nCGswKzVj5E22cDy1YF_M6MHO9K3BWRsYkVafKVd_Cjd1xnrR5/s1600-h/korythethief8.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5395371275511464034" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLsCTyDygRhHEVu4EuYyMH4U46K1iRU_SekhsM0RRZjaHl7eSy6_RQyI5SBYpZ8hJVODkzxvyWGa_aEuydX5nCGswKzVj5E22cDy1YF_M6MHO9K3BWRsYkVafKVd_Cjd1xnrR5/s400/korythethief8.png" style="cursor: pointer; display: block; height: 242px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Egypt Level 2</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">This stage introduces lasers that pulse on and off. I torment the player in this level by making the room with the jewel difficult to find. I expect many players to at first skip past the room and catch a glimpse of the jewel while falling down the corridor on the right. Of course, by then it's too late. :P</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjfbBtF7qwiupvAo8b5ar6uLjsm08W0I23-VAonx4xvyo2CMjItWglVrF9P9YvHEv_DQJ0nkoz3NKP9AYnOvmmLuoYfKAHWnQsu9ismuZS4Qzk3iFo8EM6h9HTbYju-9uu8q_v/s1600-h/korythethief9.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5395371280765411234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjfbBtF7qwiupvAo8b5ar6uLjsm08W0I23-VAonx4xvyo2CMjItWglVrF9P9YvHEv_DQJ0nkoz3NKP9AYnOvmmLuoYfKAHWnQsu9ismuZS4Qzk3iFo8EM6h9HTbYju-9uu8q_v/s400/korythethief9.png" style="cursor: pointer; display: block; height: 179px; margin-bottom: 10px; margin-left: auto; margin-right: auto; margin-top: 0px; text-align: center; width: 400px;" /></a></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Egypt Level 3</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">The final stage looks more difficult than it actually is. There are many lasers in the level, but most are easy to dodge, except the lasers on the conveyor belts. Once the player has spent a few lives figuring out how to grab the jewel, the rest of the level only requires some simple, cautious jumping before the player is out of the museum and scot-free.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">In Summary</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">-Thanks to the linear nature of the game, I was able to design the difficulty curve to tightly coordinate with the player's ever-increasing skill set.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">-In designing levels, I gave each stage its own unique shape and progression. Unique levels are memorable.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">If you are interested in designing your own levels, download Edward and give it a go.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Have fun,</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">-Greg</div>Greg Liebermanhttp://www.blogger.com/profile/08083153987589335224noreply@blogger.com0