“Am I Rich Yet?!” – Raspberry Pi Sales Monitor

April 2nd, 2016

So, I’m a publisher of an asset on the Unity Asset Store (see previous tweets, posts, shameless plugs, etc), which I sell for money(!)

It’s $30 a pop, and I don’t sell THAT many each month (we’re talking roughly 10 lately), so each sale I do make gives me a little endorphin rush. However, it’s that little rush that prompts me to then routinely check my sales page all the god damn time…

Now, obviously with only 10 of those page refreshes resulting in an uplifting rush, out of the 10,000,000 times I’ve refreshed it, that’s quite a lot of wasted time, energy and hope…

“Wait,… I own a Raspberry Pi! That bitch should be doing this kinda shit for me!” – I have a pretty gangster inner monologue…

So yes, I set about getting my lonely, bored Raspberry Pi to automatically poll my sales page, and then inform me when I’ve made a sale (preferably with a sweet ‘CA-CHING!’ sound effect).

 

Step 1: Getting the sales data.

I originally figured that I’d have to write some nifty python script to sign-in to my publisher account page with my credentials, crawl through the page HTML and parse out the juicy sales figures that I desired… but fortunately Serhii Yolkin of Lost Polygon had already done the leg-work with this and hosted a wonderful PHP API for it on github (here). What a good guy!

The API gives access to all the info I needed, and much much more. It didn’t take me long to edit down the example DemoPage.php script to instead spit out JSON data about my sales for this month:

<?php
    require 'AssetStorePublisherClient.class.php'; // Include the class
 
    // Create the client instance
    $store = new AssetStore\Client();
 
    // Login with your credentials
    $token = $store->Login('PUBLISHER_EMAIL', 'PASSWORD');
	echo $token;
 
	//$token = "YOUR_LOGIN_TOKEN";
 
    // Or, if you don't want to keep your credentials in the code, use the token (returned by Login() method or retrieved from your browser cookies)
    //$store->LoginWithToken($token);
 
    $salesPeriods = $store->FetchSalesPeriods();
?>
{
<?php
	// Use current month and year
    $salesYear = reset($salesPeriods)->GetYear();
    $salesMonth = reset($salesPeriods)->GetMonth();
 
    $sales = $store->FetchSales($salesYear, $salesMonth);
    $downloads = $store->FetchDownloads($salesYear, $salesMonth);
?>
"month": <?php echo $salesMonth; ?>,
"year": <?php echo $salesYear; ?>,
"gross": <?php echo $sales->GetRevenueGross(); ?>,
"net": <?php echo $sales->GetRevenueNet(); ?>
<?php
    foreach ($sales->GetPackageSales() as $value)
    {
        echo sprintf(',"%s_%s" : {"shortURL" : "%s", "packageName" : "%s", "price" : "%s", "numSold" : "%s", "numRefunded" : "%s", "numChargebacks" : "%s", "gross" : "%s", "first" : "%s", "last" : "%s"}', 
                     $value->GetPackageName(),
                     $value->GetPrice(),
                     $value->GetShortUrl(),
                     $value->GetPackageName(),
                     $value->GetPrice(),
                     $value->GetQuantity(),
                     $value->GetRefunds(),
                     $value->GetChargebacks(),
                     $value->GetGross() == 0 ? null : $value->GetGross(),
                     $value->GetFirstPurchaseDate() == null ? null : date('d F Y', $value->GetFirstPurchaseDate()),
                     $value->GetLastPurchaseDate() == null ? null : date('d F Y', $value->GetLastPurchaseDate())
                     );
    }
?>
}

 

Step 2: Checking for a sale

Once I had my php page returning the current sales data for my asset in a lovely JSON formatted string, I then needed to write a script to interpret this data and recognise whether a sale had been made. In order to know whether a new sale had been made, I just needed to keep track of the number of sales observed in the previous lookup. I did this by simply writing the value to a text file. I also kept a record of the month index, in order to tell when a new month had started and subsequently reset the counter data. Here’s my python script polling the sales data from the php page, and working out if any sales had been made:

#!/usr/bin/env python
# coding: utf-8
 
# Usage:
# $ fetch_fenderrio_sales_data.py PACKAGE_NAME PACKAGE_PRICE
 
import os
import sys
import httplib
import urllib
import urllib2
import json
 
if len(sys.argv) <= 2:
  print('Usage:')
  print('python fetch_fenderrio_sales_data.py PACKAGE_NAME PACKAGE_PRICE')
  exit()
 
packageName = sys.argv[1]
packagePrice = sys.argv[2]
 
 
f = urllib2.urlopen('http://localhost/packageSalesData.php')
 
jsonData = f.read().replace(" ","")
jsonData = jsonData.replace("\n","")
 
#print('Returned data:')
#print (jsonData)
 
data = json.loads(jsonData)
f.close()
 
currentMonth = data['month']
 
packageID = packageName + '_' + packagePrice
 
currentNumSold = 0
 
if packageID in data:
	results = data[packageID]
	currentNumSold = int(results['numSold'])
 
#print(packageID + ' : Num Sold : ' + currentNumSold)
 
prevSalesData = open("/home/pi/ftp/files/" + packageID, 'r+')
 
prevSoldData = prevSalesData.read()
 
prevNumSold = 0
 
if prevSoldData != '':
	# Expecting data to be in following format: MONTH_INDEX,NUM_SALES
	cachedData = prevSoldData.split(',');
	# Check that cached data was for the same month
	if int(cachedData[0]) == currentMonth:
		prevNumSold = int(cachedData[1])
 
 
# Calculate number of sales since last check
numNewSalesSinceLast = currentNumSold - prevNumSold
 
# print('Num Sold Since Last : ' + str(numNewSalesSinceLast))
 
# Write sales data back to file
prevSalesData.seek(0)
prevSalesData.truncate()
prevSalesData.write(str(currentMonth) + "," + str(currentNumSold))

 

Step 3: Send me the good news!

I toiled with a few different options for alerting myself of a new sale; email? text message? an arduino powered robot hand giving me a thumbs-up gesture?

In the end I found the perfect solution in a service called PushOver, which allows you to send push notification messages to specified mobile devices with the corresponding PushOver receiver app. All you need to do is push a request to their messages API page, with your user token and the token(s) of the devices you want to receive the message, which you can do in a million different ways with a million different programming languages (as shown on their docs site), Python being one of them! Note: PushOver is a paid service, so after a 7-day free trial, it costs a one-off $4.99, per-platform (iOS, Android, Desktop). I only needed Android, so was happy to pay a couple of English Pounds for the simple elegant service!

Here’s the final part of my python script, following on from the end of the previous code sample:

if numNewSalesSinceLast > 0:
	# Send a push notification to signal a sale(s)
	conn = httplib.HTTPSConnection("api.pushover.net:443")
	conn.request("POST", "/1/messages.json", urllib.urlencode(
		{	"token":"aP3HkP3CUQFwPDP5m3HwprvXtCbRzx",
			"user":"u8HnEYxywisb1t13NCLPAYmv6hsNMs",
			"title":"You're Rich!",
			"sound":"cashregister",
			"message":"You've made " + str(numNewSalesSinceLast) + " " + packageName + " sales since last scan! That's now " + str(currentNumSold) + " sales this month."}),
		{"Content-type":"application/x-www-form-urlencoded"})
	conn.getresponse()

 

If you’ve looked at that code closely, you may have noticed that, yes, it does use a cash register ‘CA-CHING‘ sound effect! Score!

 

Step 4: Check it 10,000,000 times, so I don’t have to…

So by this point, we have a python script which will get the assetstore sales data, interpret how many sales have been made since the last time the script was run, and then notify me if it’s more than crummy zero.

Obviously we don’t want to be running this script over and over again ourselves, so lets get a machine to do it! I’m using my Raspberry Pi, but it could be any machine that can be setup to run scheduled tasks.

On the Pi, I set up a crontab task which runs my python script every 5 minutes by adding the following line to my crontab file:

*/5 * * * * /usr/bin/python /home/pi/ftp/files/fetch_fenderrio_sales_data.py TextFX 30

 

Step 5: Profit!

That’s it! No more refreshing my sales page manually like a bloody schmuck. I can now just sit at my desk, staring intently at my phone, for hours and hours on end, waiting for it to buzz… which is so much better!

Here’s a test notification I sent to show what it looks like on device (you’ll have to imagine the ‘CA-CHING’ in your head…).

 
Of course, now I probably won’t make another actual sale ever ever again…

Hopefully this has been of interest to some of you out there! Please let me know if you have any further queries about  it all; I disabled comments on my blog posts because they get destroyed by spam, but feel free to email (fenderrio[AT]gmail.com).

General, Raspberry Pi | No Comments | Trackback

It’s Aliiive!

March 8th, 2016

I honestly thought this site was a goner… The main WordPress site mysteriously went blank  (literally just a white page) at the end of 2014, and with a new job and new city to be dealing with at the start of 2015, I left the site dormant for future Tom to deal with some day soon…

Fast forward a mere 15 months, and I discover a not-too-old backup of the site code from before the white-out, swap it all out, refresh the page, and here it is again! It’s a flippin’ miracle! I was really starting to miss it… I’ll treat it better this time around. I will.

Well, a LOT has happened since my last post. I’m now based in Manchester working for BBC Childrens as their in-house Unity developer, working primarily on their critically acclaimed and crazily popular CBeebies Playtime app. I’ve been exposed to so much new and interesting work in and around the Unity engine, and my apps development knowledge has easily quadrupled! I will endeavor to write up some individual blog posts over the coming weeks, covering some of the industry wide apps-dev problems I’ve faced, and the solutions I’ve come up with to solve them. There’s a lot I want to share!

TextFx (my Unity text animation plugin) is still very-much in continued development, with probably the biggest update since it’s initial release going out last May. It now integrates with NGUI Labels and Unity’s own UI Text components and their whole UI Canvas system, making it much more practical to implement into peoples projects. Also a whole new Quick Setup animation editor exists to allow super quick and easy setup of a number of pre-setup animations. Check out the new WebGL demo to get a better idea! http://www.codeimmunity.co.uk/TextFx/demo.php

Virtual Reality has become a reality! I have an Oculus DK2, a Gear VR and an Oculus CV1 on PreOrder (expected in June :( …). I’m in love with my Gear VR; the effect of having a polished store, polished product, and a number of really great GAMES (not just demos/experiences) to play on it, has really showed me what VR can do and where it’s going to go. I’m determined to contribute in some way to this new exciting wild-west VR development era that we find ourselves in, and am tinkering on some VR game ideas in my spare time, so expect to read some more about these in the future!

Well, that’s enough of a catch up for now. You’ll hear more from me soon!

General, Unity Development | No Comments | Trackback

Flappy Alex: In Miracle World

February 26th, 2014

I recently entered into Flappy Jam; the Flappy Bird game jam. Click here to play it! With the very simple requirements being  just to “make a hard, almost unplayable game, using assets inspired (not ripped) from classics”,  I figured it would be fun to spend a few evenings bringing to life an Alex Kidd themed flappy bird game :D

I recreated all the graphics myself using GIMP, and made full use of the great new 2D sprite tools in Unity 4.3.

Unity Development | No Comments | Trackback

Super Clone Box – Part 2

September 25th, 2013

If you missed the last post, here it is.

So, 2 weeks in, and I am absolutely loving this project! Something about seeing those little green bastards monsters strutting their stuff in all their pixelly goodness just fills me with joy :)

So, since the last update, I’ve written my own SpriteManager solution! It works in conjunction with an external sprite packing program appropriately called SpriteSheetPacker. SpriteSheetPacker just takes all the individual sprites and fits them nicely onto one texture atlas, and spits out a data text file describing the UV pixel coordinates of each frame by name. I’m then parsing this data file in my SpriteManager component as an offline pre-processing step in the editor so it has the information required to render each frame (the normalised uv coordinates based on the width and height of the texture). From here I’m able to setup any animation using those frames, and through some custom Inspector class magic, preview the animations in the Editor. It currently handles sprite mirroring, rotation and vertex colour tinting for each frame, and although the workflow could do with some tidying up and simplifying, I’m very happy with it so far and it’s enough to handle most if not all of the sprites in the game.

The second big thing that I’ve worked on since the last update, was the player controls. I was originally using Unity’s built-in rigidbody physics components, and by locking the rotation on all axis and the z-depth positioning, I was able to achieve a decent-ish 2D player control system. But, there were a number of annoying little “glitches” which I couldn’t seem to fix without losing some other crucial functionality. For instance, if my player jumped straight upwards and collided back down onto a platform, it would move a tiny amount to the side, even though everything was flat and level (perpendicular box colliders…). The problem was most noticeable when you’d jump the player repeatedly on the spot, and it would gradually move to the left (you can see it happening in the first build). I played around with the physics loop frequency and the physic material friction settings to try and prevent it, but nothing stopped it. I imagine it’s to do with some sort of rounding/approximation error when re-positioning the intersecting colliders. Unity is a 3D physics engine after all, so it probably wasn’t built to cater for the acute, twitch controls of a 2D platformer like Super Crate Box. I daresay that Unity 4.3′s promised 2D specific physics engine will help solve this problem in the future! But this is now, 4.3 isn’t out yet, so I’ve gone a different route.

For the players physics, in order to get the super fast response and feel of the original game controls, I opted to implement my own basic physics engine. I’m simulating a gravity force, checking for intersections between the player and the platforms colliders every frame, and then handling the resulting collision between them. It seems mad, I know, but it’s working! I have complete control over the players movements now, and until it starts running like a total pig, I’m gonna keep it like that :)

For the weapon name effects when you collect a new crate, I found this great text animation plugin, which did the job fantastically ;)

One more thing, a little tip for creating great high quality pixel art; create your pixel images originally at pixel scale, and then upscale them to the size you need them in your game with the quality interpolation settings set to none. This stops your image processing program from anti-aliasing all of your nice pixel crisp edges when increasing the scale! Genius. ;)

Click here for the latest WebPlayer build.

Comments and feedback are welcome!

Uncategorized | No Comments | Trackback

Super Clone Box – Part 1

September 14th, 2013

Ok, so I’m a Unity game developer, but I don’t actually have any independently developed finished Unity games to brag about to anyone and show that I CAN actually make games (“I swear I can!”). That needs to change. I’ve gotten my TextFx plugin to a stable polished state, which I’ll continue to maintain and release small updates to, but I need a new main project and that needs to be a game this time! But… making a game takes ages, especially if you keep changing your mind about what it should be like and getting distracted by other game ideas to prototype… which is what I’ve basically done over the last year or so. SO I thought of a way to hopefully speed up the development time of this game; I’ll make a game that already exists!

Deciding which game to make was easy; it’s one of my favourite games, I play it all the time, I know it inside out, it’s Super Crate Box (If you haven’t played it yet, go get it now! It’s free!  http://www.supercratebox.com/).

Lets recap my motives and intentions with this project. Primarily I’m making a Super Crate Box clone in Unity to serve as a portfolio piece and to learn more about the creation of 2D arcade games. Beyond the primary intention, I have a few ideas of where I may take things; thinking of putting it up on the AssetStore as an example project, I want to make it work on mobiles, and I might add some addition unique features to the original game to see what happens and maybe appeal to some other SCB fan-boys out there.

What I’m not going to be doing is releasing a paid Super Crate Box clone game. To start with I want to try and make as accurate a copy of the original as possible, using the original assets where possible. But if I do decide to release the game either as an AssetStore example project or as a free online SCB game mod, I will first replace all the assets with my own versions.

While I’m developing the game I’ll try to write regular blog post updates, documenting the progress and any technical challenges that have been overcome, and I’ll include webplayer build updates for people to play aswell. Hopefully it’ll be of interest to Unity developers, game developers in general and also fans of the original SCB

So I’ve spent a few evenings getting the project started, and I’m already loving it! So far I’ve just got one level, with a player, one enemy type and 5 weapons, but it’s playable and you can try and beat your highscore. Seeing as this first post is already quite long, and so far I haven’t had to tackle any real technical challenges, I’ll leave the technical breakdowns until next time! For now though, here’s a screenshot of the level in the editor window, with gizmos marking out the areas where a new crate can be spawned.

Click here for the webplayer build.

Obviously, there’s lots still to do and to tweak, so go easy with it!

Unity Development | No Comments | Trackback

TextFx Released In The AssetStore

June 3rd, 2013

TextFx – Unity Plugin - Asset Store LinkWeb Player Demo

TextFx is a text animation plugin for the Unity Game Engine, which I started working on in January 2013. Meant as a quick “one month project”, and in the end taking about 5 months, consisting of evenings and bits of weekends. But it’s finally finished! :D

I was inspired to make TextFx after working on this website late last year, and getting completely carried away making interactive headers for the site (notice above!). I then started to wonder how I’d go about making some cool text animations/effects within Unity, since I’d not done anything this fancy with Unity texts before. I’d already assumed that there was no in-built support for this in Unity, but I figured there’d be a few well embedded solutions in the Asset Store. What?! None? (None like this at least…). “Well, I guess I’ll make one then…”

I wanted to make a system that would allow you to create pretty much any text animation you could think of. It had to support in-editor offline playback, and provide instant feedback on how your effect will play and appear in the scene. It had to be quick, easy and intuitive to use. I wanted users to be able to experiment and explore different ideas as soon as they thought of them.

It’s become far more than I first envisaged back in January; the scope just kept naturally expanding as I went along! “Well, it can’t have that feature and NOT have these 3 features as well…”. But what I’ve finished with 5 months later is a product that I feel can genuinely bring something new and fresh to any Unity project, and I dream of the day when I’ll hopefully see this plugin being used in some awesome Unity games of the future!

Unity Development | No Comments | Trackback

Add copy/paste functionality to all object Transforms in Unity

December 1st, 2012

I’m going to focus my first Unity developer tutorial on something that I personally would’ve loved to know about a year ago when I started using Unity! I’m not sure how big a deal this is for other Unity devs, but the number of times I’d be playing my game in the Unity Editor, seeing how things played out, then playing around with objects in the scene while it was still running, moving everything into its perfect position, then realising that it was all going to snap back to how it was before when I stop playing that instance! Wouldn’t it be great if you could just copy the positions of the game objects in the scene and then paste them back after stopping the game…?

This tutorial will go over how to write a Unity editor extension for the Transform component, which will add “Copy/Paste” buttons to the Inspector for every GameObject in your project.

We’ll start by adding our own reverse engineered version of Unity’s built-in UnityEditor.TransformInspector class into our projects “Editor” folder. This script was based on a script posted on the Unity wiki here, and I’ve added two (currently useless) buttons, “Copy” and “Paste”.

Note: It is important that this script gets added to a folder named “Editor” in your project hierarchy, otherwise it won’t have any effect! If you haven’t got an “Editor” folder, then create one.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using UnityEngine;
using System.Collections;
using UnityEditor;
 
[CustomEditor(typeof(Transform))]
public class TransformCopy : Editor
{	
	public override void OnInspectorGUI ()
	{
		Transform t = (Transform)target;
 
		// Replicate the standard transform inspector gui
		EditorGUIUtility.LookLikeControls();
		EditorGUI.indentLevel = 0;
		Vector3 position = EditorGUILayout.Vector3Field("Position", t.localPosition);
		Vector3 eulerAngles = EditorGUILayout.Vector3Field("Rotation", t.localEulerAngles);
		Vector3 scale = EditorGUILayout.Vector3Field("Scale", t.localScale);
 
		EditorGUILayout.BeginHorizontal();
 
		if(GUILayout.Button("Copy Transform"))
		{
			Debug.Log("Copy Transform");
		}
 
		if(GUILayout.Button("Paste Transform"))
		{
			Debug.Log("Paste Transform");
		}
 
		EditorGUILayout.EndHorizontal();
 
		EditorGUIUtility.LookLikeInspector();
 
		if (GUI.changed)
		{
			Undo.RegisterUndo(t, "Transform Change");
 
			t.localPosition = TidyVector3(position);
			t.localEulerAngles = TidyVector3(eulerAngles);
			t.localScale = TidyVector3(scale);
		}
	}
}

You should now notice that all of the Transform components in your project have an additional two buttons added to the bottom. How handy!

Now lets make those buttons do something useful.
Add this static string variable to your TransformCopy class:

1
public static string TRANSFORM_COPY_PREFIX = "eqguqero124";

Add this within your “Copy Transform” button if statement (line 23 in script above):

1
2
3
4
5
6
7
8
9
10
11
12
PlayerPrefs.SetFloat(TRANSFORM_COPY_PREFIX + "_pos_x", t.localPosition.x);
PlayerPrefs.SetFloat(TRANSFORM_COPY_PREFIX + "_pos_y", t.localPosition.y);
PlayerPrefs.SetFloat(TRANSFORM_COPY_PREFIX + "_pos_z", t.localPosition.z);
 
PlayerPrefs.SetFloat(TRANSFORM_COPY_PREFIX + "_rot_x", t.localRotation.x);
PlayerPrefs.SetFloat(TRANSFORM_COPY_PREFIX + "_rot_y", t.localRotation.y);
PlayerPrefs.SetFloat(TRANSFORM_COPY_PREFIX + "_rot_z", t.localRotation.z);
PlayerPrefs.SetFloat(TRANSFORM_COPY_PREFIX + "_rot_w", t.localRotation.w);
 
PlayerPrefs.SetFloat(TRANSFORM_COPY_PREFIX + "_scale_x", t.localScale.x);
PlayerPrefs.SetFloat(TRANSFORM_COPY_PREFIX + "_scale_y", t.localScale.y);
PlayerPrefs.SetFloat(TRANSFORM_COPY_PREFIX + "_scale_z", t.localScale.z);

Add this within your “Paste Transform” button if statement (line 28 in the script above):

1
2
3
4
5
6
Undo.RegisterUndo(t, "Transform Paste");
 
// General object transform data found
t.localPosition = new Vector3(PlayerPrefs.GetFloat(TRANSFORM_COPY_PREFIX + "_pos_x"), PlayerPrefs.GetFloat(TRANSFORM_COPY_PREFIX + "_pos_y"), PlayerPrefs.GetFloat(TRANSFORM_COPY_PREFIX + "_pos_z"));
t.localRotation = new Quaternion(PlayerPrefs.GetFloat(TRANSFORM_COPY_PREFIX + "_rot_x"), PlayerPrefs.GetFloat(TRANSFORM_COPY_PREFIX + "_rot_y"), PlayerPrefs.GetFloat(TRANSFORM_COPY_PREFIX + "_rot_z"), PlayerPrefs.GetFloat(TRANSFORM_COPY_PREFIX + "_rot_w"));
t.localScale = new Vector3(PlayerPrefs.GetFloat(TRANSFORM_COPY_PREFIX + "_scale_x"), PlayerPrefs.GetFloat(TRANSFORM_COPY_PREFIX + "_scale_y"), PlayerPrefs.GetFloat(TRANSFORM_COPY_PREFIX + "_scale_z"));

You should now be able to copy and paste any objects Transform data, and paste it onto other objects. This works by saving the state of the Transform into the PlayerPrefs, which is stored locally on your PC.

In order to ensure that the transform data doesn’t get saved over any existing game data with the same key name, we’re prefixing the data keys with the unique random string TRANSFORM_COPY_PREFIX.

Unity Development | No Comments | Trackback

New Blog Started!

September 5th, 2012

Hi everyone, I’m Tom Figg, author of this here new blog.

I’m a computer games developer and general application programmer. Check out my previous works under the Portfolio section of this site.

Here I’ll be blogging about various development how-to’s and also my personal projects and independent releases.

I’ll be mainly aiming my content at fellow programmers and games development enthusiasts.

I’m currently quite an avid Unity game engine fan, using it for my day job and in my personal projects, so expect there to be an emphasis on Unity development to start with!

General | No Comments | Trackback

Recent Posts

  • 21 days ago

    Combining two of my favourite things; Spelunky and cool Unity dev stuff. Great tutorial! https://t.co/hFISvey3nZ

  • 35 days ago

    @_jemmah you were right... I did like that :)

  • 47 days ago

    Pumped to be adding bezier curve support to TextFx soon! Works with Unitys animation system too #unity3d #assetstore https://t.co/gbwd02NZGQ

  • 50 days ago

    Got my Playstation VR demo slot booked for EGX Rezzed on Friday! We'll see how it compares! #VR #EGXRezzed

  • 52 days ago

    @Fenderrio sending my sales updates using @superblock 's fantastic PushOver service. Very slick. And they have a cashregister sfx! Perfect

  • 52 days ago

    @Fenderrio It makes great use of @Lost_Polygon 's Unity Publisher API

  • 52 days ago

    I got sick of refreshing my sales page every 30sec, so I got my Raspberry Pi to do it for me! Blog post: https://t.co/hLMQbKrwOs #assetstore

Archives

Categories

Meta