If you cannot view this newsletter correctly, click here to view it online
(2) FPSC News (3) FPSCR Videos (4) AGK Development (5) Echoes+ (6) Video Games Book (7) Birney's Run (8) Live Programming (9) AGK V2 Sensors (10) DarkForge (11) Social Feeds (12) TGC Channel
Each month we update you on the progress of FPS Creator Reloaded. You'll find a running commentary on the development through the FPSC-R Blog, but right here you will find some of the selected highlights that deserve your utmost attention. You can also follow the development on the official Facebook page. Within the R&D offices here at TGC, Reloaded is our main focus and we aim to constantly develop it to make it into a world class game creation tool. With great support from people who have made pledges to the project we are able to evolve and build our best game maker ever!
Lee Bamber, FPS Creator Reloaded Developer summarises the September achievements for himself and the FPSCR development team.
Starting with the current task at hand, this week is performance week. I will be using Intel VTune to find all CPU bottlenecks and squash (or redirect) them as much as possible. I have some major areas I think need work, but I will let the profiler be my guide this week. I started by switching off every component and running the profiler on a completely empty scene, no terrain, objects, sky, physics, anything. I then had a look at what might be hogging things. The engine seems to be monitoring all the objects - even if they are invisible - for things like animation potential, mesh vertex update potential and other large loops. The first profiler-lead change was to ensure the texture sort only happened when the overall number of objects in the engine changes (i.e. something gets added or removed). I immediately went from 143 FPS to 208 FPS by adding two extra lines of code and a new variable!
I won't tease you with my current frame rate gains as they are very subjective but I am happy to report that for every bottleneck I find, and eliminate, the bottom line FPS jumps up. There is still the unavoidable issue that the engine drops back down to the 40 range when I try to draw a thousand shaded objects, but that is something I plan to tackle separately as it relates back to visuals and how the rendering order and quantity is handled.
We have focused on the lighting question again, all very necessary stuff but it's slow progress making concrete decisions. You could not find a more subjective topic to talk about, and committing ideas to code requires a very clear understanding of what you want to do, versus what do not want to happen. Three hours of experimentation and analysis resulted in a solution; a new slider value called 'Surface Level', and much like 'Ambient Level' controls the intensity of the multiplier within the shader, but this time for direct light. I also added the remaining shader controls to the new static render effect to include shadow intensity and general ambient and surface colors. Before I started the week of speed, I had one last visual related conference call with one of our former top artists.
Taking five minutes away from his cut and thrust industry artist lifestyle, he helped us come up with a plan on how we might balance the lighting system in our engine and create a more impressive final render. I will only be starting this work mid-October but it's great to have another pair of eyes, attached to a brain and mouth that can talk in the language of code and the language of art. We can only benefit from his help!
Crowd funding provides a way for Indie Developers like The Games Creators to pre-fund their projects. It's also a thumbs up from customers to show the developers the market wants and needs their new idea.
By pledging you are helping The Games Creators to build the most exciting and revolutionary game creator. With your pledging support you can strengthen our team as we build this amazing technology. You are essentially becoming part of our family as you share in it's development and ultimate production.
All pledge levels grant the backer access to all betas, with other bonuses, including free model packs valued at between $18 and $39 for Gold and Silver pledge levels.
So, if you'd like to help fund Reloaded development and join us on our journey, please support us with a pledge. The most popular and best value deal is the Gold level pledge, but you can find details of all pledge levels here.
FPS Creator Reloaded is now airborne! You can own the Jet Pack that inspired this additional capability simply by referring a friend to pledge to the project. They'll also get the Jet Pack, along with four additional textures worth a total of $30USD.
We have another video tutorial on our YouTube channel for you this month. You can of course subscribe to our channel and get immediate updates; the details are towards the end of the newsletter.
A tutorial showing how to use the sliders in Reloaded and how to get the best out of them
Again this month, we see great leaps forward with Version 2 of App Game Kit. Alpha 7.1 is the very latest release and with it comes more functionality, more Mac compatibility and more happy pledgers!
The key features added in this release are:
Broadcasting on the Mac OS X Platform
Essentially, this means it is now possible to develop and test entirely on a Mac. There is no need to have a virtual machine running, or a secondary Windows computer.
Exporting to Android APK on Windows and Mac
Exporting to APK files on the Mac also allows you to remain within your OS X environment to complete the publishing process.
Exporting to IPA on Mac
Smoothing the final build, it is also possible to export IPA files, the executable required for iOS deployment. This relies on Mac OS X functionality to achieve.
New Sensor Commands on iOS and Android
Where devices have gyros, magnetic and proximity sensors, these can now be interrogated by Android, iOS, Mac and Windows 7 devices. There are some very clever inclusions in respect of rotation vectors, that essentially enable very easy VR implementation.
RotSensorW# = GetRawRotationVectorW2()
RotSensorX# = GetRawRotationVectorX2()
RotSensorY# = GetRawRotationVectorY2()
RotSensorZ# = GetRawRotationVectorZ2()
SetCameraRotationQuat( 1, RotSensorW#, RotSensorX#, RotSensorY#, RotSensorZ# )
GPS Support
If your device supports GPS, then you can implement it in your projects. This opens up a whole new avenue of possibilities, and we look forward to seeing what you can do with it.
Here is a full rundown of the updates in Alphas 6, 7 and 7.1:
Updates
Fixes
The core language is very solid, has a bunch of great features and when problems inevitably do crop up they are addressed and fixed quickly
Recently published is this Video Games-making book by Nick Pendriis. In it, he works step by step through the process of conceptualising, designing and building a video game. The book covers assets, testing, publishing and promoting too, so you'll have information on every aspect of the lifecycle of game development.
Naturally, the book makes reference to AGK and DarkBASIC as good options to start your gaming adventure.
The book is available in electronic format for your Kindle or other reading device at Amazon.
Birney feels a bit peckish! Help him munch his way through a labyrinth full of delicious vegetables.
In Birney's Run, your goal is to eat as many vegetables as possible to get the highest score. But beware, four slimes are on their way and they will do their best to kick you out of the maze.
Birney's Run is easy to learn. After a quick tutorial, you'll know everything you need to compete with the best. The catch is that every level requires a different strategy! Should you rush to the exit before there are too many slimes? Or should you eat these crunchy carots for extra points? Think fast, every level is more difficult than the previous one.
Birney's Run features two different game modes:
This application is ad-supported but you can remove ads permanently for $1.19 (£0.69). That is the only in-app purchase item available. No need to pay to progress! No way to pay to cheat!
Daniel regularly contributes to the TGC community with tutorials, both written and recorded. He has now taken a step further and produced a Live video of the coding of Pong, the game many an aspiring coder starts with. This version is written in App Game Kit V2, and there are no clever edits and cuts. What you see is the coding process from start to finish, errors included!
The highly anticipated Sensor commands arrived in AGK Version 2 with the Alpha 6 build. These extend the command set to gyro, magnetic, GPS, accelerator and light commands. The easiest way to see how they work is to write a little code and check the outputs.
The following code is a simple testbed. It is not written for efficiency or elegance, merely to visualise the output from the sensors. For anyone new to AGK or encountering unseen concepts, the code is described briefly. Some best practise techniques are also highlighted in this article. Firstly, here is the output we are going to produce:
Firstly, we'll create a type, tVector3. This will allow us to neatly record X, Y and Z values.
type tVector3
x as float
y as float
z as float
endtype
Next we have a number of variables declared. These are to simplify fine tuning the code, setting screen positions and so forth. For example, you can alter these to change the length of the sensor bars, and reactivity of the sensors. These values never change once the program is running.
global vec as tVector3
global diff# as float
global spacing as integer
global height as integer
global left as integer
global length as integer
diff# = 0.05
spacing = 34
height = 28
left = 500
length = 200
The sensor values will be retained in an array. There are three values (X, Y and Z) for each of the accelerometer, gyro and magnetic sensors. We also need the screen position for each value, and the sprite that will be used for its bar. The easiest way to achieve this is using a type again.
type tReading
x as float
y as float
value as float
length as integer
sprite as integer
endtype
dim arrReading[8] as tReading
To reference each sensor, the following constants are declared:
#constant cAX = 0
#constant cAY = 1
#constant cAZ = 2
#constant cGX = 3
#constant cGY = 4
#constant cGZ = 5
#constant cMX = 6
#constant cMY = 7
#constant cMZ = 8
This may seem like a lot of additional code for very little advantage. As we will see, it allows some operations to be carried out en masse. If the program was to expand then this method would become more advantageous very quickly. The first shortcut follows, where all of the sprites are quickly created and positioned.
curY = 0
for n = 0 to 8
arrReading[n].sprite = createSprite(0)
setSpriteposition(arrReading[n].sprite, left, n * spacing)
next n
You will recall that if we have miscalculated any of the positions, spacing and sizes, we can adjust the value at the top of the program,and it will propogate throughout all of the calculations.
Within our main program loop, we will be repeating a series of processes for each of the sensors. In order to understand what is happening, here is the process isolated for just one sensor, the X acceleration sensor.
vec.x = (GetRawAccelX() - arrReading[cAX].value) * diff#
arrReading[cAX].value = arrReading[cAX].value + vec.x
setSpriteSize(arrReading[cAX].sprite, abs(arrReading[cAX].value * length), height)
if arrReading[cAX].value < 0
SetSpriteColor(arrReading[cAX].sprite, 255,0,0,100)
else
SetSpriteColor(arrReading[cAX].sprite, 0,255,0,100)
endif
print("X Acceleration: " + str(arrReading[cAX].value,3))
do
vec.x = (GetRawAccelX() - arrReading[cAX].value) * diff#
vec.y = (GetRawAccelY() - arrReading[cAY].value) * diff#
vec.z = (GetRawAccelZ() - arrReading[cAZ].value) * diff#
arrReading[cAX].value = arrReading[cAX].value + vec.x
arrReading[cAY].value = arrReading[cAY].value + vec.y
arrReading[cAZ].value = arrReading[cAZ].value + vec.z
setSpriteSize(arrReading[cAX].sprite, abs(arrReading[cAX].value * length), height)
setSpriteSize(arrReading[cAY].sprite, abs(arrReading[cAY].value * length), height)
setSpriteSize(arrReading[cAZ].sprite, abs(arrReading[cAZ].value * length), height)
vec.x = (GetRawGyroVelocityX() - arrReading[cGX].value) * diff#
vec.y = (GetRawGyroVelocityY() - arrReading[cGY].value) * diff#
vec.z = (GetRawGyroVelocityZ() - arrReading[cGZ].value) * diff#
arrReading[cGX].value = arrReading[cGX].value + vec.x
arrReading[cGY].value = arrReading[cGY].value + vec.y
arrReading[cGZ].value = arrReading[cGZ].value + vec.z
setSpriteSize(arrReading[cGX].sprite, abs(arrReading[cGX].value * length), height)
setSpriteSize(arrReading[cGY].sprite, abs(arrReading[cGY].value * length), height)
setSpriteSize(arrReading[cGZ].sprite, abs(arrReading[cGZ].value * length), height)
vec.x = (GetRawMagneticX() - arrReading[cMX].value) * diff#
vec.y = (GetRawMagneticY() - arrReading[cMY].value) * diff#
vec.z = (GetRawMagneticZ() - arrReading[cMZ].value) * diff#
arrReading[cMX].value = arrReading[cMX].value + vec.x
arrReading[cMY].value = arrReading[cMY].value + vec.y
arrReading[cMZ].value = arrReading[cMZ].value + vec.z
setSpriteSize(arrReading[cMX].sprite, abs(arrReading[cMX].value * length / 45.0), height)
setSpriteSize(arrReading[cMY].sprite, abs(arrReading[cMY].value * length / 45.0), height)
setSpriteSize(arrReading[cMZ].sprite, abs(arrReading[cMZ].value * length / 45.0), height)
for n = 0 to 8
if arrReading[n].value < 0
SetSpriteColor(arrReading[n].sprite, 255,0,0,100)
else
SetSpriteColor(arrReading[n].sprite, 0,255,0,100)
endif
next n
print("X Acceleration: " + str(arrReading[cAX].value,3))
print("Y Acceleration: " + str(arrReading[cAY].value,3))
print("Z Acceleration: " + str(arrReading[cAZ].value,3))
print("X Gyro: " + str(arrReading[cGX].value,3))
print("Y Gyro: " + str(arrReading[cGY].value,3))
print("Z Gyro: " + str(arrReading[cGZ].value,3))
print("X Magnetic: " + str(arrReading[cMX].value,3))
print("Y Magnetic: " + str(arrReading[cMY].value,3))
print("Z Magnetic: " + str(arrReading[cMZ].value,3))
Sync()
loop
SetVirtualResolution(1024,768)
SetSyncRate(30,0)
type tVector3
x as float
y as float
z as float
endtype
global vec as tVector3
global diff# as float
global spacing as integer
global height as integer
global left as integer
global length as integer
diff# = 0.05
spacing = 34
height = 28
left = 500
length = 200
type tReading
x as float
y as float
value as float
length as integer
sprite as integer
endtype
dim arrReading[8] as tReading
#constant cAX = 0
#constant cAY = 1
#constant cAZ = 2
#constant cGX = 3
#constant cGY = 4
#constant cGZ = 5
#constant cMX = 6
#constant cMY = 7
#constant cMZ = 8
curY = 0
for n = 0 to 8
arrReading[n].sprite = createSprite(0)
setSpriteposition(arrReading[n].sprite, left, n * spacing)
next n
do
vec.x = (GetRawAccelX() - arrReading[cAX].value) * diff#
vec.y = (GetRawAccelY() - arrReading[cAY].value) * diff#
vec.z = (GetRawAccelZ() - arrReading[cAZ].value) * diff#
arrReading[cAX].value = arrReading[cAX].value + vec.x
arrReading[cAY].value = arrReading[cAY].value + vec.y
arrReading[cAZ].value = arrReading[cAZ].value + vec.z
setSpriteSize(arrReading[cAX].sprite, abs(arrReading[cAX].value * length), height)
setSpriteSize(arrReading[cAY].sprite, abs(arrReading[cAY].value * length), height)
setSpriteSize(arrReading[cAZ].sprite, abs(arrReading[cAZ].value * length), height)
vec.x = (GetRawGyroVelocityX() - arrReading[cGX].value) * diff#
vec.y = (GetRawGyroVelocityY() - arrReading[cGY].value) * diff#
vec.z = (GetRawGyroVelocityZ() - arrReading[cGZ].value) * diff#
arrReading[cGX].value = arrReading[cGX].value + vec.x
arrReading[cGY].value = arrReading[cGY].value + vec.y
arrReading[cGZ].value = arrReading[cGZ].value + vec.z
setSpriteSize(arrReading[cGX].sprite, abs(arrReading[cGX].value * length), height)
setSpriteSize(arrReading[cGY].sprite, abs(arrReading[cGY].value * length), height)
setSpriteSize(arrReading[cGZ].sprite, abs(arrReading[cGZ].value * length), height)
vec.x = (GetRawMagneticX() - arrReading[cMX].value) * diff#
vec.y = (GetRawMagneticY() - arrReading[cMY].value) * diff#
vec.z = (GetRawMagneticZ() - arrReading[cMZ].value) * diff#
arrReading[cMX].value = arrReading[cMX].value + vec.x
arrReading[cMY].value = arrReading[cMY].value + vec.y
arrReading[cMZ].value = arrReading[cMZ].value + vec.z
setSpriteSize(arrReading[cMX].sprite, abs(arrReading[cMX].value * length / 45.0), height)
setSpriteSize(arrReading[cMY].sprite, abs(arrReading[cMY].value * length / 45.0), height)
setSpriteSize(arrReading[cMZ].sprite, abs(arrReading[cMZ].value * length / 45.0), height)
for n = 0 to 8
if arrReading[n].value < 0
SetSpriteColor(arrReading[n].sprite, 255,0,0,100)
else
SetSpriteColor(arrReading[n].sprite, 0,255,0,100)
endif
next n
print("X Acceleration: " + str(arrReading[cAX].value,3))
print("Y Acceleration: " + str(arrReading[cAY].value,3))
print("Z Acceleration: " + str(arrReading[cAZ].value,3))
print("X Gyro: " + str(arrReading[cGX].value,3))
print("Y Gyro: " + str(arrReading[cGY].value,3))
print("Z Gyro: " + str(arrReading[cGZ].value,3))
print("X Magnetic: " + str(arrReading[cMX].value,3))
print("Y Magnetic: " + str(arrReading[cMY].value,3))
print("Z Magnetic: " + str(arrReading[cMZ].value,3))
Sync()
loop
It sounds like the title of an epic RPG. Let me assure you, it's better than that.
Come on a journey with me, as we enter once again the Dark Forge.
Rich Davey is a name known by many of the older members. He was part of the TGC team and started this very newsletter back in January 2003. As an active member of the community before his tenure at The Game Creators, he created many demos and games that inspired many creations, and much of his work was included in other games.
I caught up with Rich recently, intrigued by the idea of taking some of his original demos from DarkBASIC Classic - some written last century - and running them on a modern PC. The late nineties was still an era when clock cycles were your most precious possession.
As a result of our discussion, Rich has released all of his DarkBASIC oriented assets to the community. This not only includes the demos and games, but also the source code, and even the DarkForge website!
You can download the entire package here. Be warned it is around 170 Megabytes in size. We'd love to see anything you do with this code make it's way onto the forums, even if it's just to say you got it running again.
You can read the accompanying article on Rich's Photon Storm website, where you'll get an insight into the early days of DarkBASIC, and the communitry around it.
Join over 6,400 fans on TGC's Facebook page to keep bang up to date on news, user projects from the forums and discussions.
We're keen to hear from all our avid users and we always love to hear what you've been up to with the tools we sell. So if you have something you want to share with the wider TGC audience why not post it into the TGC Facebook page?
There are now over 3,700 fans discussing Reloaded on our Facebook page right now. Whether you simply want to see the update and progress news as it is released, or get involved in technical discussions about LOD, Light and lots of other topics, sign up to this page today to be part of it.
You can join in the Facebook discussions in our AGK group page with over 600 members and we have a new AGK Facebook page.
You can also follow our products on Google+
Have you visited the TGC YouTube Channel yet? You may be surprised:
Take a look at our channel now, and make sure you hit the subscribe button to stay up to date with new video uploads. Very often you'll get advanced previews of upcoming news.
"Accept certain inalienable truths: Prices will rise. Politicians will philander. You, too, will get old. And when you do, you'll fantasize that when you were young, prices were reasonable, politicians were noble and children respected their elders."
Mary Schmich