Android Indie Games

http://www.alcove-games.com le blog de El_Porico.

Leaderboard custo: comment ca marche

Monday 15 July 2013 à 7:11

Pour Fireworks j’ai code moi meme un petit leaderboard, tout simplement parceque je hais les solutions integrees ou il faut creer un compte et qui rajoutent une surcouche a votre app Android.

Comment ca marche?

Tout d’abord il va vous falloir une base de donnees et un petit PHP. Chez moi c’est sur un Ovh Pro a 6e/mois.

Donc il nous faut une table avec nos users:

CREATE TABLE IF NOT EXISTS `users` (
`id` varchar(255) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`created` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

Et une table pour nos scores:

CREATE TABLE IF NOT EXISTS `scores` (
`score_id` int(11) NOT NULL AUTO_INCREMENT,
`id` varchar(255) DEFAULT NULL,
`level` int(11) NOT NULL,
`score` int(11) NOT NULL,
`maxcombo` int(11) NOT NULL,
`stars` int(11) NOT NULL,
`updated` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`score_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1

… Pensez aux index qui vont bien aussi.

maxcombo et stars sont specifiques a l’app, mais bon vous pouvez mettre ce que vous voulez.

Maintenant il va falloir un bout de code PHP pour envoyer/recevoir des donnees, et de meme pour Java. Le tout doit etre encrypte. Car si les infos sont envoyees en clair n’inporte quel petit malin peut ecouter les packets HTTP et poster des scores delirant. Ca va se faire en AES 128 bits.

Cote PHP, il nous faut definir notre cle privee:

define(’CYPHER_IV’,”deadbeef00112233″); //cle privee

En Java la meme:

private static String CYPHER_IV = “deadbeef00112233″;

Ensuite il va falloir faire transiter du flux binaire par POST et envoyer du binaire dans la reponse. PHP peut tres bien faire ca. Mais pour pas se prendre la tete j’ai decide de tout transferer sous forme de chaine hexa. Ca aurait pu etre du base64. La chaine hexa c’est un peu lourd (il faut 2 octets pour en transferer un seul) mais au final tres peu de donnees transitent donc ca va tres bien.

En PHP on bin2hex et bin2hex. En Java, il a fallu se le tapper a la main:

    private static byte[] hex2bin(String hex) {
        String HEXINDEX = "0123456789abcdef";
        int l = hex.length() / 2;
        byte data[] = new byte[l];
        int j = 0;

        for (int i = 0; i < l; i++) {
            char c = hex.charAt(j++);
            int n, b;

            n = HEXINDEX.indexOf(c);
            b = (n & 0xf) << 4;
            c = hex.charAt(j++);
            n = HEXINDEX.indexOf(c);
            b += (n & 0xf);
            data[i] = (byte) b;
        }

        return data;
    }

    public static String bin2hex(byte buf[]) {
        StringBuffer strbuf = new StringBuffer(buf.length * 2);
        int i;

        for (i = 0; i < buf.length; i++) {
            if (((int) buf[i] & 0xff) < 0x10)
                strbuf.append("0");

            strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
        }

        return strbuf.toString();
    }

Maintenant, il nous faut en Java un truc pour envoyer des donnees en POST. Et on fait des requetes en GET:

    public static String post(String key, String value){
       
        //encode data
        EncryptedString es = Fireworks.aes.encrypt(value);
        String ret = "";
       
       
        if(es == null) return ret; //failure at encryption??
       
        try {
            // Construct data
            String data = URLEncoder.encode(key, "UTF-8") + "="
                    + URLEncoder.encode(es.publicKey + es.message, "UTF-8");
            /*
            data += "&" + URLEncoder.encode("key2", "UTF-8") + "="
                    + URLEncoder.encode("value2", "UTF-8");*/

            // Send data
            URL url = new URL("http://www.superscript.com/monscript.php");
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            OutputStreamWriter wr = new OutputStreamWriter(
                    conn.getOutputStream());
            wr.write(data);
            wr.flush();

            // Get the response
            BufferedReader rd = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
           
           
            String line;
            while ((line = rd.readLine()) != null) {
                ret += line + "\r\n";
            }
            wr.close();
            rd.close();
        } catch (Exception e) {
        }
       
        return ret;
    }

    public static String get(String querystring){
        //return "bcfc85cefc9d6000252112e8ab50c226,1,Guest,20247,0,0\r\n";
       
        String ret = "";
        try {

            // Send data
            URL url = new URL("http://www.superscript.com/monscript.php?" + querystring);
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            OutputStreamWriter wr = new OutputStreamWriter(
                    conn.getOutputStream());
            wr.write("");
            wr.flush();

            // Get the response
            BufferedReader rd = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            conn.setDoOutput(true);
           
            String line;
            while ((line = rd.readLine()) != null) {
                ret += line + "\r\n";
            }
            wr.close();
            rd.close();
        } catch (Exception e) {
        }
       
        return ret;
    }

Le truc important, c’est qu’a chaque fois que des donnees transitent, vous devez generer une cle publique. Dans le POST on la met dans une variable a part, par contre dans le GET j’ai fait le sioux. Le resultat retourne par le serveur et la concatenation de la cle+des donnees:

Du coup dans le PHP on fait un truc du style:

if(isset($_POST['getscore'])){
    $getscore = trim($_POST['getscore']);
    if(preg_match('/^[a-f0-9]+$/',$getscore)){
        $data = '';
        if(strlen($getscore) > 32){
            $key = substr($getscore, 0, 32);
            $data = substr($getscore, 32);
            $data = decrypt($data, $key);

Bref, les plus chevronnes peuvent me contacter s’ils veulent directement les sources. Autrement il n’y a rien de bien complique. Pensez a threader les requetes POST et GET pour ne pas completement bloquer le jeu.

Petite preview de pxup.me

Sunday 16 June 2013 à 17:06

Alors que je me connecte a uppix.net vendredi dernier pour uploader une image, je tombe desesperement sur:

Migration in progress”

Damn it! J’ai pas le choix, j’ai du lancer filezilla et uploader une image a l’ancienne. La poisse. Mais comme j’avais pas grand chose d’autres a faire au bureau, j’ai lance mon WAMP prefere, code comme un petit fou tout excite par le pissage de code, et finalement j’ai accouche de pxup.me.

La home

Bref, c’est simplement un service d’hebergement d’images. Ni plus, ni moins.

J’ai une petite liste de bugs a corriger et surtout la preview d’images ne fonctionne toujours pas. Par contre, l’upload lui fonctionne sans probleme. Mais comme on est dimanche soir ici, je me suis dit que j’allais poster une petite update. Considerez le site comme beta jusqu’a ce que je fixe le restant, c’est a dire demain.

Y’a du drag and drop HTML5 tagada tsoin tsoin qui va bien. J’en suis pas trop mecontent.

Heroes Defense TD WIP

Monday 6 May 2013 à 3:50

Cela fait maintenant quasiment un mois que j’ai poste ici meme une annonce pour level designers pour mon prochain jeu Android.

J’ai plusieurs reponses dont Nomys_Tempar qui a concocte quatre niveaux plutot bien foutus. Voici la tete que ca a:

YouTube Preview Image

Sous le capot pas mal de choses ont change. Par exemple, on peut maintenant accelerer la vitesse du jeu jusqu’a 4x, une feature indispensable des tower defenses. Pour ce changement j’ai du modifier la boucle du jeu pour qu’elle tick precisemment a 1/60s en lieu et place du framerate naturel. On evite ainsi les effets de bord si le deltatime to chaque frame est trop grand (physique qui pete et projectiles qui traversent les ennemis au lieu de les toucher, entres autres).

Autre chose, le jeu commencait a prendre trop de temps a charger. Rien de bien mechant, 4 secondes max sur mon telephone, mais c’est suffisemment long pour que les utilisateurs se demandent si le jeu est pas en train de planter. J’ai donc implente un loading screen qui charge toutes les ressources sur un thread dedie. Je ne voulais pas de loading screen, mais bon force est de constater que charger une petite dizaines de textures 32bits 1024×1024 (40mo de memoire) est beaucoup demander a mon Galaxy S2.

A ce propros je build regulierement le jeu pour voir si les ajouts que je fais ne sont pas trop impactant sur les perfs. Pour le monent tout tourne toujours a 60fps donc je n’ai rien a craindre de ce cote.

Il faut dire qu’il y a plein de petites optimisations que l’on peut facilememt realiser.

Par exemple: l’archer peut tirer autour de lui jusqu’a 5 cases. Soit 10×10 = 100 cases a check sur chaque frame s’il y a pas un ennemi a prendre pour cible. Au lieu d’appliquer ce comportement, au moment ou on positionne un archer, un petit algo construit la liste des cases sur ce carre de 10×10 qui sont sur le chemin des ennemis. Dans la pratique, on itere donc sur une 10aine de cases. 90% de gain vs un petit de calcul au moment du positionnement: je prends!

Il y a d’autres comportements que je garderai ou pas. Par exemple l’archer et le mage blanc lancent des projectiles. Ce projectile ne peut que toucher le mob pris pour cible. Dans la pratique ca veut dire que potentiellement on a l’impression que certaines projectiles traversent les mobs. Chercher precisemment pour chaque projectile s’il est pas en contact avec des dizaines d’ennemis a l’ecran, je me demande si c’est pas un peu trop cher en perf. A tester…

Les heros sont d’ailleurs quasi entierement codes. Dans cette video on peut voir les 5 en action.

D’autres nofrages ont voulu faire un decors sur le tileset donjon mais il y a un probleme sur les tiles… Du coup avant de se lancer dans un build de carte je me dois de remettre tout ca dans l’ordre et fournir un scenario pour que les maps collent a l’histoire. J’y travaille.

D’ailleurs j’ai envoye pas mal d’infos aux interresses pour faire du level design sur vos adresses wefrag mais je n’ai pas eu de retour (skaven, MrHelmut, Chaka). Vous avez bien tout recu?

Sur la TODO:

  • In game menu (pause, redemarrer un niveau, retour a l’ecran titre)
  • Corriger le tileset dungeon & cave pour les rendre Tiled friendly
  • Integrer le son
  • Integrer des effets de particule (du sang!)
  • Le menu principal d’ailleurs, pas du tout commencer
  • Equilibrer les persos (pour l’instant les valeurs sont fixees arbitrairement)

Voila pour une update. Ca avance sur son petit rythme mais ca commence a avoir de la guele.

Recherche un level designer

Thursday 11 April 2013 à 16:08

Je cherche un level designer pour mon prochain jeu (un tower defense) Android.

Inutile de tourner autour du pot, deja voila a quoi ca ressemble:

YouTube Preview Image

C’est donc, comme vous pouvez le constater, un tower defense tout ce qu’il y a de plus classique. Je suis derriere la programmation et tous les artworks sont des ressources d’OpenGameArt/licenses CC ou autres domaine publique. Malheureusement, je me rends compte que programmer le bousin prend deja un temps considerable, et que je n’ai aucun talent pour le level design.

Votre mission si vous l’acceptez, sera donc de designer environ 30 niveaux pour le jeu, 10 par environnement (grassland, cave, dungeon), les niveaux etant de plus en plus compliques et alambiques.  Chaque niveau doit comprendre les fameuses waves d’ennemis, a setupper dans un fichier de config simple.

Les maps sont editees avec Tiled, un truc que meme votre grand mere peut utiliser. Mais le talent pour faire quelque chose de joli, c’est autre chose:

tiled

Les differents tilesets sont l’oeuvre de Clint Bellanger, qui les fournit en license CC BY SA. Voila ce qu’on peut faire avec pour info:

0052

0033

La question maintenant est: est-ce que ca paye?

Il y aurait peut etre des nofrages ici qui seraient prets a aider benevolement, mais la reponse est oui, ca paye, mais peu, parceque je suis un pauvre mais que votre travail doit quand meme valoir qq chose. Concretement je suis pret a reinvestir tous les gains de mon precedents jeu (200 USD) dans votre modeste personne, ou proposer un autre format de “contrat” –type 50 USD + x% des gains de celui ci. A voir. Faites des propositions.

La remuneration ne doit PAS etre votre source de motivation principale soyons clairs. Vu les heures que vous allez passer la dessus, autant dire que vous etes payes 5% du SMIC. Je fais ce que je peux.

Bref, si vous etes motives jpeux vous en dire plus: contact chez alcove-games.com

Fireworks jeu android: bilan après 2 mois

Sunday 3 February 2013 à 9:14

Cela fait maintenant un peu plus de 2 mois que mon app est publiée sur le Google Play Store.

Bref, c’est l’heure d’un premier bilan!

Tout d’abord, avec une moyenne de 4.6, l’app a été plutôt favorablement reçue… Mais le Google Play Store est assez complexe. Les downloads sont au final peu nombreux (toujours moins de 2000); mais fait étrange, ces 15 derniers jours il y a eu plus de 500 téléchargements; en fait depuis que j’ai franchis la barre des 1000. Il y a forcement dans l’algorithme de Google quelque chose qui nous positionne mieux dès qu’on atteint le seuil de 1000.

Répartition des downloads en Janvier

J’ai rapidement compris que Google Play ne fonctionnerait pas terrible, c’est pourquoi j’ai également publié l’app sur le Samsung App Store et l’Amazon App Store; et plus récemment sur Getjar et SlideMe.

En cumulant les infos des stores et d’AdMob, j’en arrive ce résultat:

En décembre il y a eu un gros eCPM. C’est une période forte pour la pub et ca s’est prolongé tout le mois de Janvier. Je pense que les revenus vont rapidement diminuer en Février. Il faut vraiment que je me sorte les doigts et que je fasse une update.

C’est un peu compliqué depuis que j’ai mon nouveau job; mais il y a le semaine du nouvel an chinois bientôt et j’espère être un peu productif pendant les jours fériés.

A très bientôt ;-)

Fireworks - 3 semaines plus tard

Tuesday 4 December 2012 à 5:17

CCela fait maintenant un plus de 3 semaines que Fireworks est publié et comme promis voici un bilan.

Tout d’abord comment se porte l’app? Elle stagne dans les tréfonds du Google Play Store.

fireworksAvec un peu plus de 250 installs. Pas très réjouissant.

Pourtant, j’ai passé pas mal de temps à tenter de promouvoir le jeu. Il y a une review sur appegg et sur un autre site. Les autres sites de reviews sont des arnaques complètes, y compris les très gros brassant des centaines de milliers de vue/jour.

Ces sites m’ont fait clairement comprendre que si je voulais une review c’était +/- $100. C’est un élément assez sombre des apps Android aujourd’hui. Si vous voulez de la visibilité, ne comptez pas sur la presse. Elle est malhonnête et biaisée en fonction de la taille de votre portefeuille.

L’autre problème est que le jeu avec un nom aussi générique que “Fireworks” est difficilement trouvable sur l’app store.

Par contre, là où ça devient intérressant, c’est que j’ai publié l’app récemment sur le Samsung Store; et malgré la taille toute petite de ce store, les impressions de pubs ont été multipliées au moins par 6 par jour; ce qui prouve que ce qui pose problème sur mon app, c’est avant tout son manque de visibilité.

Le dernier jour ne compte pas, il n'est pas encore comptabilité

Le dernier jour ne compte pas, il n'est pas encore comptabilité

Avec si peu d’utilisateurs, cela a généré $8 et 3 semaines. Bref d’ici un an je pourrai m’acheter une bouteille de champagne ;-)

Ceci dit, le marché de la pub mobile est assez horrible. Si je prends les stats admob; un click rapporte en moyenne 3 cents. C’est horrible. Pour gagner $1000 par mois, il faudrait environ 2 000 000 d’impressions de pubs par moi avec un taux de clic moyen.

D’un autre côté, si je pense qu’un jeu comme celui là pourrait être developpé en 1 semaine en étant à plein temps; c’est pas si mal.

Du côté des updates; un nouveau niveau et un nouveau type de rocket est prévu. J’espère publier ça avant le nouvel an.

Le prochain sera un tower defense

Monday 19 November 2012 à 14:46

Ca fait un peu plus d’une semaine que Fireworks est publié. J’ai pas mal de choses à dire mais je garde ça pour ce weekend.

En attendant, c’est décidé, mon prochain jeu sera un tower defense.

Etant donné que je n’ai aucun talent de graphiste, j’ai récupéré un peu partout pas mal d’artworks dans le domaine public ou sous license CC et j’ai de quoi faire un jeu.

Concept Art

Concept Art

Comme tout tower defense qui se respecte, des vagues d’ennemis passeront donc un chemin et vous devez les tuer. L’archétype du jeu à jouer dans les chiottes. On est en terrain connu.

L’originalité c’est qu’on ne placera pas des tours, mais des personnages. Chevalier, archers, mages et autres; tout un joyeux petit monde pour dézinguer des centaines d’ennemis. On pourra donner l’ordre aux personnages de se déplacer. Un peu comme si on avait des tours mobiles. Ca donne un intérêt stratégique supplémentaire à ce genre complètement surexploité.

Côté programmation, j’ai déjà le moteur de rendu pour tiles isométrique, et l’animation des personnages est +/- prête.

Finalement, en quelques centaines de lignes de code, j’ai un proof of concept intéressant.

Evidemment, comme je dev à mes heures perdues; ca sortira vraissemblablement dans 6 mois :p

Qu’importe, maintenant que je me suis fait les dents sur Fireworks, tout est possible!

Fireworks! dispo sur l’app store

Tuesday 13 November 2012 à 3:22

C’est fait, “Fireworks!” est dispo sur l’app store depuis maintenant 3 jours.

La dernière ligne droite n’a pas été facile et je me suis battu avec Illustrator pour créer des screenshots et images promotionnelles pour le store. Quand on est pas expert avec ces logiciels, on galère pas mal.

Image hosted by uppix.net Image hosted by uppix.net Image hosted by uppix.net Image hosted by uppix.net

Ensuite j’ai soumis le jeu a des dizaines et des dizaines de sites webs avec des reviews pour générer du traffic. Amis, reddit, forums, emails; bref je fais ce que je peux.

Lien vers lappstore

Lien vers l'appstore

J’essayerai d’écrire un “post mortem” - d’ici un mois pour faire un point où le jeu en est et quelles conclusions je peux en tirer pour le prochain.

Les stats Google sont un peu lentes à se mettre à jour mais je peux monitorer l’activité en temps réel grace au leaderboard. Depuis la publication du jeu, il y a donc eu 27 joueurs uniques qui ont posté au total 117 scores.

Cela signifie qu’un joueur en moyenne s’arrête au monde 4 (sur 6).

Mais on aura le temps de reparler de tout ça dans quelques semaines quand il y aura des vrais chiffres! Pour le moment, je n’ouvre pas encore le champagne mais je savoure le fait que le jeu se retrouve sur le store!

Je tiens au passage à remercier tous les nofragés qui m’ont donné du feedback. J’ai pas mal d’idées d’updates grâce à ça; ca viendra assez rapidement je l’espère!

Fireworks - jeu android prerelease

Sunday 4 November 2012 à 10:03

Ca y est! J’arrive au bout!

Telécharger l’APK [10mo]

Le jeu est maintenant entièrement jouable et il sera publié sur l’app store dès que j’aurai fignolé tout ça. Je me donne 2 semaines.

Par rapport à avant on a donc:

  • Tous les types de rockets jouables
  • 6 mondes, 3 levels par monde. Chaque monde apporte un nouveau type de rocket
  • Leaderboard fonctionnel
  • Une “musique de fond” sur le niveau de jeu avec fondu enchainé sur le thème principal
  • Vibrations à l’explosion -désactivable.
  • Un Tuto! pour le premier niveau
  • … Des dizaines de petits bugs corrigés

Je suis vraiment content des deux dernières rockets ajoutées; elles envoient du poney. On a donc une grosse supernova qui finie en pluie étoilée et une autre qui tourbillonne a l’explosion. La prémière est faite en bidouillant une force de friction f=-kv et la 2nde on ajoutant une force perpendiculaire à la vitesse (cross product avec le vecteur v et un vecteur aléatoire). Ca rend pas mal mais toutes les critiques sont les bienvenues ;-)

Le tuto... Parcequil faut bien vivre avec son temps!

Le tuto... Parcequ'il faut bien vivre avec son temps!

Côté background qu’on ne voit pas; le jeu est désormais entièrement passé en OpenGL ES 2.0: plus de fixed pipeline. Ca ne change strictement rien à l’aspect graphique du jeu mais devrait permettre un gain de perfs sur certains mobiles. Pour rappel OpenGL ES est un fork pour mobile des specs OpenGL. OpenGL ES 2.0 correspond +/- à une fondue mélangeant du OpenGL 2.x, OpenGL 3.x & OpenGL 4.x.

Action in game... Dur de jouer et prendre des screens potables en même temps!

Action in game... Dur de jouer et prendre des screens potables en même temps!

J’ai également sérieusement nettoyé le code puisqu’il compile maintenant sans aucun warning. D’une manière générale, le code est plutôt clean même si j’ai pas mal hacké de choses sur la fin.

Il me reste 2 trucs à faire avant de publier:

  • Améliorer les bruitages. Le son est à chier comme depuis le début.
  • Animer les 3 derniers tableaux. Pour le moment c’est une image statique.

Maintenant je me rends compte d’une chose. Il y a donc 6*3 = 18 niveaux. Chaque niveau se termine en ~1 minute, un peu plus pour les derniers niveaux. Ca fait en gros le jeu torché en un peu plus de 20min tutorial inclus. C’est un vrai problème. Quoi qu’il en soit, je vais publier le jeu en l’état et je pense rajouter un mode infini ainsi qu’un 7ème tableau (et donc un 7ème type de roquette) par la suite.

J’arrive à un moment où si je rajoute plus de choses le jeu ne sera jamais publié; alors il faut faire un choix. Ceci dit je pense que ça reste parfait pour glandouiller dans les chiottes/bus/métro (rayez les mentions inutiles) et c’est le but de tout jeu de tel portable.

Telécharger l’APK [10mo]

Bref, si vous n’aviez pas encore testé, c’est le moment ou jamais! Et pour les fidèles qui installent des versions boiteuses sur leurs machines depuis quelques mois maintenant, j’aimerai bien avoir vos retours aussi ;-)

opengameart.org

Tuesday 28 August 2012 à 16:09

Si vous allez sur opengameart.org, vous trouverez une communauté de fous furieux qui filent comme ça, gratos, sous license CC-BY pour la plupart, des tonnes de textures, sons et models 3D pour des jeux.

Je suis tombé sur un superbe tileset isométrique, et quelques personnages pas trop pourris.

Test de rendu

Test de rendu

Du coup j’ai pas pu résister à l’envie de bricoler vite fait un rendu de la chose. Ca ferait un chouette RPG au tour par tour. Mais bon pour ça il faudrait que je quitte mon boulot et que je bosse dessus à plein temps.

Bref, c’était juste pour partager le lien. Retournons aux choses sérieuses…