“Les meilleures années de ta vie”

So today I’m going to do a post in french, because I’m french, and this article has been in the writing for so long that I’d better like it left in french. In case you’re wondering what it’s about, it’s a recap of my 5 years of school in computer science. Nothing too fancy, but there’s a lot to say.

Disclaimer : En aucun cas êtes-vous autorisés à utiliser ce texte dans son intégralité ou en partie à des fins commerciales ou de promotion quelconque. J’ai volontairement omis les noms incriminant, je suis ouvert à la discussion si l’article dérange. Je tiens à préciser que ceci est mon point de vue, mon expérience, et n’est pas représentatif de ce que tous les étudiants ont vécu.

Je vais vous raconter une histoire. Banale pour la plupart d’entre vous, mais vu que c’est celle de ma vie, je m’essaie de croire que ça ne l’est pas, car personne n’a vraiment envie de vivre une vie banale.

La première année : définition de l’entropie

Tout démarre en novembre 2009, dans la petite bourgade de Bordeaux. Notre héros, petit Tuxic a tout juste 18 ans (bon, depuis 6 mois, mais ça compte pas) et rentre dans sa toute nouvelle école sur laquelle il lorgnait depuis la fin de sa seconde. Petit Tuxic est excité, il va faire de l’informatique, du code, il est content, il sautille. Surtout qu’il sort de 2 mois d’ermitage total et d’une addiction sévère aux meuporg, qui s’était terminée brutalement sur une overdose à cause d’un certain Aion (depuis 2009, je n’ai jamais réussi à apprécier un MMO de nouveau). Mais voilà, les nouveaux locaux, annoncés en grande pompe la semaine d’avant ne sont pas prêts. On lui dit de revenir la semaine prochaine, parce qu’il y a encore plein de travaux à faire. Petit Tuxic se dit “Chouette, une semaine en plus de vacances!”. Et c’est ainsi que j’étais rentré dans le merveilleux monde de l’enseignement supérieur.

Ma première année pourrait être qualifiée de catastrophe naturelle à juste titre. Au premier semestre, tout se passait bien. Notre promotion était toujours dans l’esprit scolaire, on avait des profs marrants, on apprenait plus ou moins des trucs, bref, ça passait. Je m’ennuyais quand même pas mal, et puis j’avais du mal à me faire des amis. Oui oui. Puis il y a eu le second semestre, et quelque chose est arrivé. Quelque chose d’assez grave que je ne m’autoriserais pas d’en parler précisément parce que je tiens sérieusement à ne pas terminer au tribunal. Quoi qu’il en soit, les choses sont devenue carrément moins marrantes à l’école : les réunions s’enchainaient pour nous dire que tout allait bien avant qu’elles nous disent que tout allait mal. Progressivement, tout le monde a commencé à dire que sur Bordeaux on était qu’une bande de connards, alors que nous, les premières années, on n’avait aucune idée de ce qui se passait. Du coup on a commencé à choisir nos camps, et je vous explique pas l’ambiance en cours quand on discutait de ce qui se passait.

Mais heureusement, il s’est passé des trucs cool pendant cette année:

  • Mon oncle m’a pris en stage à temps partiel tous les mercredis dès le début de l’année. J’ai pu bosser en entreprise dès le début, faire du web, beaucoup de web, et gagner mes premiers “salaires” que je claquais quasiment instantanément dans du matos totalement inutile.
  • Je m’étais lancé dans le podcast vidéo orienté tech parce que ça me faisait rire, et que je mattais le Geek Inc et que je trouvais ça trop classe. A l’époque, mes podcasts passaient pas sur Youtube, car trop longs. Oui, vous savez, ce temps où il n’y avait pas de pubs preroll et que les vidéos pouvaient pas dépasser 15 minutes.
  • J’ai fait connaissance avec
  • Je me suis mis à Twitter

Oui mais voilà, il est aussi arrivé une de mes meilleures expériences sur internet :

  • Petit Tuxic se met à touiteur
  • Petit Tuxic relate les faits de son école, les problèmes qu’on a sur place, ce qu’il vit sur le champ de bataille
  • Petit Tuxic se retrouve linké sur les forums privés de l’école par des gens bien attentionnés
  • Petit Tuxic se fait rouler dessus par 5000 étudiants plus fervents qu’un armée de fans Apple sur touiteur pour avoir relayer de l’info

Oui, mesdames et messieurs, en 2010, je me suis fait mon propre bad buzz avant même que ça soit un terme, et depuis je peux vous le dire : YO FUCKING LO. Certains individus nourrissent encore une certaine haine à mon égard, alors que perso aujourd’hui, j’en ai plus rien à péter. D’ailleurs, cette merveilleuse expérience m’a permis de me décider sur le camp à choisir dans cette guerre stupide : pas celui où des étudiants en rut cachés derrière des handles pioupiou te crachent à la gueule. J’étais donc passé dans le camp des séparatistes, parce que voilà quoi.

Durant l’été 2010, j’ai fait une mini mission pour ma mère avec , et j’ai donc changé d’école, reniant une année entière de wtf.

La seconde année : on est bien là, hein?

La seconde année est arrivée un peu comme le messie pour quasiment toute la promo : nouvelle école, nouvelle philosophie, et plein de cours, PUTAIN DE OH MON DIEU C’EST ENORME. On va pas y aller par 4 chemins, ce fut mon année la plus studieuse. Tout d’abord parce que quasiment tous les cours étaient excellents, les profs aussi, l’ambiance n’était plus à la guerre thermonucléaire (malgré l’occasionnel boulet qui venait m’emmerder sur twitter), bref, on était bien. De mon côté, ce fut une année bien solitaire du point de vue de l’école : mis à part et quelques autres, j’avais toujours du mal à me faire des amis :sadtuxic:. Et pourtant, ce fut une année assez forte en rencontres.

Le labo games. Un pan entier de ma vie. J’y suis rentré en tant qu’étudiant tout frais parce que c’était tout neuf, parce que je voulais faire des jeux vidéo, parce que le directeur avait l’air cool, et puis parce que voilà, on est aussi là pour s’amuser un peu! Je peux dire sans problème que les laboratoires ont été les meilleurs moments de toute ma scolarité. J’y ai rencontré mes futurs collègues d’Imagine Cup, beaucoup de personnes qui sont maintenant de bons amis et surtout une passion renforcée pour un sujet qui me donnait vraiment envie, le jeu vidéo. Pourtant dans les faits, toute personne saine aurait pu dire du laboratoire que c’était pas normal que ça tourne. Pour faire simple, le labo games s’est créé au dernier moment et n’a donc attiré que peu d’étudiants (on était 13, quand des labos avaient une bonne 50ene d’étudiants). Ce qui a fait qu’en général, les directeurs des laboratoires nous considéraient souvent avec un peu de dédain, du genre “de toute façon, c’est un labo placard” ou “ils savent faire que jouer aux jeux vidéo” (entendu à la pause café). Evidemment, cela a duré jusqu’à ce que l’école se rende compte de notre potentiel : nous avions participé à une montée en compétence jusqu’à noël 2010 parce que beaucoup de jeunes ne savaient pas coder de jeux. Du coup, le laboratoire s’était retrouvé en décembre avec 5 ou 6 mini jeux (je crois que je les ai encore sur une clé usb) et là, l’école s’est dit “mais oui! Il faut les montrer! Pub pub pub!”. On a eu droit à des demandes de mettre des logos de l’école à la place des pièces, des petites mentions spéciales, l’obligation de présenter nos créations en JPO, des trucs qui disent “oui, ce sont nos poulains” alors que nous étions la pire des merdes quelques semaines plus tôt. Nous avions assez souvent des contacts avec des professionnels, et dans notre cadre une jeune entreprise de gamedev faite par des anciens étudiants qui nous coachaient sur les projets. Ils nous ont introduit à l’Imagine Cup de Microsoft, dans le but de nous faire gagner, évidemment. A partir de ce moment, c’est devenu un peu bizarre : on nous autorisait à disparaître de cours pour se concentrer sur la compétition, on possédait les clés des locaux, on restait jusqu’à pas d’heure parce qu’il fallait développer des jeux. On a même eu une semaine entière de banalisée juste avant le rendu final pour finir les jeux. Bon, l’histoire veut que mon équipe se soit viandée comme des pro, mais une autre équipe ayant participé dans la catégorie jeux en Silverlight (l’Imagine Cup a beaucoup changé) a pu se qualifier à la finale française, et une équipe du labo de Toulouse est allé plus loin en remportant la médaille d’or en jeux sur Windows Phone. Bref, petits fours et étoiles dans les yeux, le labo games, c’était The Laboratoire to be.

Du coup, à travers l’Imagine Cup, j’ai rencontré des gens de Microsoft, dont quelques uns ont été d’une importance cruciale dans la suite de mes études. Par respect, je ne mentionnerais personne, mais si vous lisez ceci et que vous vous reconnaissez, sachez que je ne saurais jamais vous remercier suffisamment! Nous avions eu une Windows Day sur notre campus, avec son lot de présentations de technologies, et de la vente de rêve qui va bien. En plus on faisait plein de technos MS pour l’Imagine Cup, du coup, j’étais pas mal là dedans à ce moment.

Mais la deuxième année, c’est surtout un prof en particulier. Avec lui, on a fait approximativement 600 heures des meilleurs cours de toute ma vie : des maths appliquées, de la prog, de la logique, des trucs méga funky. Ce prof, c’était le ciment de l’année 2010-2011, et ça, c’est vraiment cool. Tu vois, l’impression d’avoir payé pour quelque chose de vraiment bien et utile? Bah c’était à ce moment.

Du coup, j’ai enchaîné sur un stage qui m’a littéralement dégoutté du web, en particulier le combo php/mysql. A l’origine, avec , on devait bosser sur ce stage avec du node.js. Du coup, l’école nous avait sorti en fin d’année de nos cours pour aller aux cours de 4eme année de node.js. Voilà, le truc démarrait bien, sauf que dernier moment, le projet est parti en mode “nope, php/mysql c’est moins cher/plus fiable”. Du coup j’en ai pleuré pendant 4 mois. C’est con hein?

Pendant le stage, j’ai eu la surprise de voir que j’étais devenu Microsoft Student Partner. Et ça, wesh, c’était grave la classe.

Par ailleurs, pendant ce stage, avec ce qui compose aujourd’hui l’association , nous avions hésité à mettre $14 dans un bitcoin, parce qu’on trouvait ça un peu cher. On s’en veut encore, on en pleure régulièrement.

La troisième année : it’s happening

Quand la troisième année a commencé, la première chose qui m’est passé par la tête, c’était que j’avais survécu à mon stage, et que ça, c’était bien. Sauf qu’en fait, pendant l’été, avec notre prof préféré qui était aussi directeur pédagogique, j’avais participé aux syllabus de l’année qui arrivait. Beaucoup de bonnes choses, des nouvelles technos, des profs qui avaient l’air super cool, et grave de la motivation de pouvoir participer à tout ça. Dans les faits, les syllabus n’avaient pas été retenu, probablement trop complexes/coûteux/pas assez “waou trop cool”. Donc à la place, on a eu des trucs qui étaient très bien (big up pour les cours de Java) et des trucs un peu vachement moins bien (non, le cours de français écrit, je ne te regarde pas). On a aussi eu pas mal de nouveaux dans la promo, et bon forcément, les niveaux de compétence disparates, c’est jamais une bonne chose.

Bref, ça commençait plutôt mal, et je ne vous cache pas qu’on était déçus dans l’ensemble; du moins ceux qui avaient vécu l’expérience depuis la première année. Mais c’était sans compter sans le laboratoire games. On était devenus une méga usine à étudiants maintenant qu’on faisait la renommée de l’école : de 13, on est passés à 35, avec plein de petits nouveaux, et plein de projets dans la tête. De mon côté, je devenais cette année co-directeur avec le créateur du labo, ce qui me donnait un peu de puissance, mais pas trop. Bon forcément, je vous passe les “je veux faire le prochain Call of Duty” et je vous parle du déroulement du labo : on s’est divisés en deux entre l’Imagine Cup et un projet en collaboration avec l’association Bordeaux Games. Je ne gérais pas le projet Bordeaux Games, mais celui ci avait des difficultés parce que les étudiants étaient jeunes et apprenaient à utiliser Unity3D (qu’on avait négocié comme des porcs parce que l’école ne voulait pas prendre de licence étudiante). Côté Imagine Cup, c’était la folie : on devait absolument pondre un jeu qui allait en finale mondiale. Le mot d’ordre, c’était qu’on devait forcément faire un jeu sur Windows Phone, exit la catégorie Xbox. Ensuite, les cours passaient tous au second plan, on bossait exclusivement sur l’IC, et ça nous arrivait souvent de venir à l’école un samedi, voire un weekend complet parce qu’on avait coaching/hackathon. C’était stressant, c’était violent, mais du coup avec les potes (dont <3) on a pondu Ecosya, notre bébé qui nous a amené jusqu’à Sydney et nous a permis de revenir avec une petite médaille d’argent. Le projet n’aura pas fonctionné sur le long terme hélas pour des raisons purement humaines (on a merdé quoi), mais ce jeu est un peu la fierté de mes études.

Du coup, les cours.. bah je les ai pas trop vu. C’était un peu le shopping là dessus, on allait à ce qui nous plaisait, et on ignorait totalement les notes, parce que de toute façon, tout nous était justifié. Je ne cacherais pas qu’on en a bien profité, mais surtout on a joué le jeu de l’école : tu fais quelque chose pour moi, je te rends la pareille. Comme une entreprise au final. Cela ne veut pas dire qu’on a rien appris de l’année, mais cela a mis en place l’idée qu’on payait l’école pour qu’on puisse faire nos trucs dans notre coin sans être gênés.

Par ailleurs, cette année s’est terminée sur un stage qui n’en était pas un : nous voulions avec les amis monter une société autour d’Ecosya. Du coup on a négocié avec l’école pour être nos propres maîtres de stage pour faire nos affaires, en particulier porter le jeu sur iOS, Android, et le maxi bonus pour l’Imagine Cup, Windows 8 (qui, rappelons le, n’était pas sorti à ce moment là). Au final, ce stage a été un échec en dehors de l’Imagine Cup, aucun portage n’a été réussi, aucune boite n’a été montée. Vous pouvez rentrer chez vous, plus rien à voir.

La quatrième année : “c’est qui Julien Noble?”

J’ai du faire une semaine de cours sur cette année ; la première semaine. La promo ne m’a vu que par instant pour le reste de l’année. Après tout, quasiment plus personne du cercle proche venait en cours, et s’étaient cassés en Chine, et bon, les cours, c’était pas spécialement mieux. Du coup, je continuais de gérer le labo Games, sachant que j’avais refusé de refaire l’Imagine Cup, parce qu’il faut pas déconner.

Cette année là, je m’étais mis en auto entrepreneur, et je faisais des trailers de jeux, parce que ça faisait de l’argent de poche, et même, c’était plutôt lucratif. J’étais pas cher (même si on a souvent tenté de me la faire à l’envers), du coup ça permettait d’acheter un burger en plus en allant au McDalle. Sans compter que j’étais très dépensier à l’époque pour faire plaisir à la personne de ma vie à ce moment (et on voit où ça m’a mené tout ça). Du coup, je faisais des vidéos, souvent privées ou pour des événements ponctuels, mais je faisais aussi des jeux vidéo parce que ça marchait bien : en avril 2012, j’avais participé à un hackathon spécial Windows Phone, et j’avais gagné un téléphone pour un mini shooter codé dans le weekend. En plus de ça, j’avais fait une micro vidéo de présentation qui avait été relayée par pas mal de sites d’actu sur les technos MS, et du coup, j’étais plutôt au top de ma popularité internet (mon kikimètre klout explosait). Du coup, j’ai fait une version plus plus du shooter sur Windows 8, et ça a marché nickel puisque je me suis fait un peu de maille, et ça, c’est toujours bien. Bref, les choses allaient bien d’un point de vue projets perso, parce que j’avais plein de choses pour m’occuper, et en plus pas le temps de m’ennuyer avec les events de Microsoft.

Parce que sinon en cours… bah putain, c’était nul si j’ose dire. Autant les laboratoires m’occupaient parce que les jeunes avaient toujours besoin qu’on soit là pour les aider, autant le reste, on se faisait chier. Les cours étaient devenus lourds, inintéressants, non formateurs. La faute à des profs non pédagogues et l’incapacité du corps enseignant à se remettre en cause. On avait eu d’ailleurs de graves soucis cette année là parce que l’école nous voyait comme une promo de petits cons jamais satisfaits. Du coup, en terme de crédibilité, on en avait pas, et présenter notre cas nous valait un claquage de porte dans les règles. En plus, j’étais délégué cette année là, je sais honnêtement pas ce qui m’était passé par la tête. Heureusement, j’avais profité suffisamment pour pouvoir utiliser les temps de cours à des projets intéressants.

Le plus comique, c’était qu’on devait faire 2 jours par semaine en entreprise ou sur un projet attribué et noté par l’école. Il se trouve qu’à aucun moment on m’a demandé ce que je faisais, je suis passé entre les mailles de ce système parce que je connaissais la bonne personne pour ça. C’en est arrivé à un point où on m’a demandé de prendre des photos pour les brochures de l’école à la fin de l’année alors que j’avais été un cancre sans nom.

Puis j’ai rencontré Sensorit, et je suis parti à Paris en stage d’été, et ça, c’était vraiment vraiment cool. D’ailleurs, je bosse chez eux aujourd’hui, pour vous dire à quel point c’était cool.

La cinquième année : Deus Ex Cancera

Durant l’été, il avait été question de gros partenariats, de faire de l’innovation, de recommencer à vendre du rêve, parce que c’est important de vendre du rêve. A ce propos, j’ai lâché le labo games pour monter le labo Innovation. C’était une idée très conne, mais au moins on s’y est bien marrés : quasiment toute la bande y était, entre qui co dirigeait le labo, , et ,  puis , et qui nous rendaient visite souvent. On n’a pas beaucoup innové, si ce n’est dans la création de vide dans le rayon bière du Carrefour market.

Honnêtement, j’avais qu’une seule hâte : retourner à Paris pour faire mon stage de fin d’études et en finir avec tout ceci. J’ai disparu de la circulation des communautés Microsoft, je me suis planqué comme pas possible, j’essayais de me faire oublier en attendant avril. Bon évidemment, ça a pas raté, j’ai eu droit à quelques remarques peu flatteuses sur mon style de vie en rapport avec l’école de la part de quelques étudiants, mais rien de bien méchant. J’ai retenté l’Imagine Cup cette année là, et je me suis fait éliminer très rapidement, probablement parce que mon jeu était trop complexe. Je ne faisais que de brèves apparitions à l’école, en laboratoire tout au mieux. Le fait était que j’en avais marre.

Pour tout vous dire, entre février et avril, juste avant de partir sur Paris, je me suis mis sur un CDD dans la société de pour pouvoir m’occuper le temps restant, parce que les cours étaient inutiles, parce que j’avais pas envie d’être dans l’école. C’est con d’en arriver là. Surtout que pendant ce temps, mon image était placardée sur des flyers, et les brochures de l’école, puis les faux sourires en JPO, en disant d’un air demi faux “oui, l’école s’adapte à ce que tu cherches à faire”. Oui, c’est pas faux, mais c’est probablement pas ce que tu penses. Je n’ai rien spécialement contre l’école, j’avais juste envie qu’elle me laisse tranquille, je ne voulais plus rien avoir à faire avec eux.

Je ne vous cacherais pas que l’année a été très difficile : j’enchaînais une absence de vie étudiante avec des problèmes personnels allant du très grave au vraiment monstrueux, et tout ce que j’espérais, c’était que ça se termine vite.

 

Maintenant que c’est terminé, je me dis que j’ai peut-être raté quelque chose. Ma mère m’a toujours dit que les années études étaient “les meilleures années de ta vie”, et pourtant, j’ai pas l’impression d’en avoir profité à fond. Il m’est arrivé des choses fantastiques, j’ai vécu des événements que je souhaite voir arriver à n’importe lequel de mes amis (Sydney par exemple), mais j’ai l’impression que tout ceci m’a filé entre les doigts, que c’est probablement passé trop vite. J’ai connu la galère, les fins de mois difficiles, les projets qui finissent très mal, mais j’ai surtout rencontré des gens formidables, vécu des instants mémorables. Et pour rien au monde je le changerais.

Maintenant je suis en CDI chez Sensorit, j’ai une situation stable, quoique j’espère qu’elle s’améliore rapidement. Mon début d’année 2014-2015 a été particulièrement horrible, entre départs, désillusions et le fait de se retrouver seul dans une nouvelle ville. Mais bon, j’y crois, on est pas non plus là pour déprimer.

Puis si c’était facile, ça serait pas marrant.

Tuxic

Fuck This Jam post mortem : Strategy.min

This week (May 31st – June 6th) happened the Fuck This Jam online gamejam, hosted and created by the awesome dudes over at Vlambeer (Super Crate Box, Luftrauser, Ridiculous Fishing, Nuclear Throne, the awesomeness just goes on…). The point was to create a game in a genre you hate or don’t know much about and put it on itch.io. Since I already had 2 or 3 projects already running at work, I decided now was the right moment to get back into gamedev again. Fuck logic.

So yeah, I made a “RTS” game. I don’t particularly hate RTS, but it just so happens that I’ve never developed one before, mostly because my mentors where like “this is so out of fashion, facebook city builders is the shite”. It had occured to me to actually do a Clash of Clans clone or some stuff like that since I hate these kind of games. I ended up doing things a whole lot differently : a sort of defend your base against a brainless AI RTS with fixed camera, minimal graphics and no resource collection. Thus was born Strategy.min. But as a matter of fact, things went pretty wrong this week, because it seems I cannot lead 20 lives at the same time.


So, what went right:

  • I actually released, which is a thing
  • I had rather solid gamedesign, but I’ll talk more about it later
  • Architecture was really fine, I pushed Unity and Mono’s compiler to its limits
  • I only ever used one outside asset : Share Tech Mono from Google fonts
  • I suck at graphics design, and I ain’t even mad after my ugly units and buildings
  • What I could do with the time I had was rather neat
  • Unity export (y)

What went wrong:

  • Even though I has solid GD, the current released version has almost 3/4 cut out because I didn’t have the time to do it properly. In the intended GD, I had bases, player constructions, research/upgrades and even a basic AI that was totally doable. Problem is I really didn’t get the time for that (see “what went horribly wrong”)
  • Mouse management was actually a pain in the ass because my system is not flexible enough
  • Architecture was fine until I realized I didn’t have the time to do everything. Then things turned ugly. Working in a prototype specialized company surely helps.
  • Flight patterns for planes is rather weird and collision detection is absent
  • Didn’t get time to do sfx and music :'(
  • YOLO : didn’t do a single code versioning on this project

What went horribly wrong:

TIME MANAGEMENT. God I suck at this. For starters, I lost all the week end figuring out what I wanted to do, and I ended up doing game design at 1am on monday morning. Since I have a job during daytime, I had mostly reserved my evenings for code and beer. Things went right on the first night, but later on, there where spontaneous “heroic fantasy tv series” or “wassup dude, wanna hang out”. The point is, when I could have had a shitton of time to dev, I actually spent like 8 to 10 hours on the game only.

Notes to future self:

  • You suck at time management
  • stop wasting time on pointless details when you’re already short on it
  • pizza, you’re eating too much of it

Well, things never go according to plan anyways. I’ll take the time to finish it, I really enjoyed working on it. Thanks to Vlambeer for putting up that event, it feels great to do games again. Download the game for free on Itch.io :

Have fun, code safe,

Tuxic

Cheetah3D to Babylon.JS exporter

Lately, I’ve been working a lot on MacOS X on 3D stuff, and I got the chance to take a look at how Cheetah3D works. For those who don’t know about it, it’s a mac only 3d software that’s not expensive and simple enough for devs like me to handle. It’s powerful enough to be used as a quick prototyping tool and a complex scene renderer. I’ll leave the technical details to 3d artists, but the point is I had to use it for realtime stuff.

This realtime stuff included native opengl on iOS and more recently webgl on your browser. Not being influenced or whatsoever, I recommended Babylon.JS for the work, and we went with it. That’s all that I can say regarding my job, so let’s go straight to the point : I made a simple export script for Cheetah3D to transform your scene into a babylon file which you can load in your browser. You can download and fork it on my github. Install is simple enough : just drop the js file into /Users/YOUR_USER/Library/Application Support/Cheetah3D/Scripts/Macro/. This is a macro script for those who know a bit about Cheetah3D scripting, meaning it covers a lot of things : reading the scene, parsing, creating and saving a file. If you want to export your scene, just go to Tools/Scripts/Macro/Babylon file export in Cheetah3D.

So, what can you do right now? It’s far from totally complete compared to babylon file specifications, but here’s what you get:

  • mesh export with functional transform, naming and parenting
  • multicamera export (only perspective, no support for orthogonal right now)
  • light export with all babylon type managed :
    • Cheetah3D spot light is a babylon spot (duh)
    • Cheetah3D distant light is a babylon directional light
    • Cheetah3D ambiant light is a babylon hemispheric light
    • every other type is a babylon point light
    • supports diffuse and specular color
    • rotations must be on the -Y axis
  • materials export:
    • supports diffuse, emissive and specular color (plus specular power as “shininess”)
    • supports only diffuse textures, Cheetah3D api is realy sparse on that

That’s it for first version, more features will come over time. Don’t hesitate to review my code as I really suck at javascript. That said, Cheetah3D’s api has got to be the worst thing in the world, including documentation that’s at least 2 years old (Material class method rib() doesn’t exist and is still documented), properties that don’t even exist and the most random descriptions I’ve had the displeasure to see in a documentation. If you ever do an export script for Cheetah3D : uvCoord() method on the PolyCore class returns a 4D vector combining first UV (x,y) with second UV (z,w). That took me forever to find out even though it seems simple.

Regarding licence, this script is under WTFPL :

DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. You just DO WHAT THE FUCK YOU WANT TO.

To resume :

Anyways, enjoy, feedback pls. Protip : don’t go loading your 60 million polygons models into Babylon.JS, chances are your browser will create a singularity.

Have fun, code safe.

Tuxic

Unity2d entities in a 3d world, why you shouldn’t do this

Sometimes I have really stupid ideas and a bit of time to waste. The base architecture for my st’hack challenge is an example of that, how I can really push a bad idea pretty far.

As you probably know (I like this formula, I use it a lot), a few months ago, Unity released its native 2d layer, with tons of new components, and a fully integrated workflow with existing 3d tools. That actually caught my interest : can you do a 3d game with the new 2d entities? The st’hack project was the perfect sandbox for this test, as I was into random dungeon generation. So, with my tileset and some Sprite game objects, can I generate a full 3d dungeon. The point is that the Sprite workflow is really simple, and it’s basically a drag and drop to create a 3d transformable entity. If you’ve checked out my executable, you’ll realize that there are no height levels, the whole dungeon is flat. It is still rendered in 3d with Sprite game objects, and as you might have seen, it’s awfully buggy.

Let’s breakdown the problems:

  • sometimes, the dungeon won’t generate. This is actually fairly easy to understand and the base limit to my idea : Unity2d entities, even though 3d objects, limit themselves to 2 axis, X and Y. What happens, at random, is that at object generation, something resets the Z axis which I use for depth placement. This means that every gameobject gets positioned on the 0 value of the Z axis, and since the player starts around [-16,0,-16], well… you can’t see any dungeon (duh)
  • the Sprite class draws on call order, and since the Z axis is not taken in account, there is no notion of depth testing. Meaning that if a Sprite gameobject behind another is drawn after the latter, it gets drawn in front of it. Overlapsing and shit, and this call order is pretty random on the same draw layer. You can in fact organize them with the draw layer feature, but this is totally wrong when it comes to 3d projection, as this needs to be totally dynamic when you modify the view model.
  • shaders. I can write a lot on this, but it actually is a noticeable problem with base 2d workflow in Unity. There is no dynamic lighting notion for Sprite objects by default. No matter what type of light or render type you choose, it won’t do anything on a Sprite object. This can of course be bypassed by changing the draw shader to a manually created diffuse sprite shader (create a new material and select this shader, affect it as material to Sprite Renderer). This should be enough if you remain into a 2d projection, but when it comes to 3d, you get the previous problems plus a shitload of math what the fucks from the Sprite class.

So yeah, it’s pretty impractical. And definitely a bad idea. Don’t do this at home kids.

So, what’s next? I plan on redoing this demo properly, aka the hard way : create true 3d objects with textures instead of sprites, reuse my algorithm, release this open source. And everyone will be happy, and the world will keep turning.

Have fun, code safe.

Tuxic

#sthack : Unity2D, dllimport and Monty Python

On the 14th of march 2014 went on the 4th edition of St’hack, a computer security event in Bordeaux that consists of a whole day of security conferences followed up by a Capture The Flag contest, organized by our very own security guru For the 4th year, I’ve been part of the staff, taking care of CTF support at first, then UI design last year. I had the opportunity to create a challenge this year (and hand out pizza and redbull).

Those who know me also know that I really suck at computer security. Idiots would be like “that’s normal, you use MS tech”, but I would be like “I fell more into video games than security these past years”. Yeah, I use Windows as my main OS, deal with it. So I thought about a game concept the powners would have to reverse to find the solution. Here’s what I came up with : a basic hack n’ slash in which the hero has to move from chamber to chamber in the correct direction (much like I don’t remember which zelda) in a limited amount of room changes. If the hero changes too many rooms without finding the correct path, he loses. He can also get killed by cheaty ogres and the level generation is rather buggy (I’ll talk about that in another blog post). There is also no information whatsoever, you are on your own.

DungeonOfLolwat

So, how do you win? I actually made the game with Unity and used a feature only available for pro versions (I think) : dllimport. The feature itself is something available with C# since the dawn of ages, but Unity has decided you have to pay to use it in your games. That appart, it requires you to understand a bit on how .Net (and Mono + Unity by extension) compile their dynamic libraries : it’s managed code, executed on a virtual machine and totally controlled by it. It means that when you compile your C#, VB.Net or managed c++ in Visual Studio, you create an intermediate language (IL) version of your code that the VM will compile on the run so that the CPU understands it. This is called Just In Time (JIT) compiler and is a rather complex and nasty business. Check out this Telerik blog post if you’d like to know more. As a sidenote, .Net is not the only tech using JIT compiling, it’s rather common these days, so haters go home (unless you just hate JIT, which I can understand).

Back to business : IL code means easy decompiling. And when I say easy, I mean that you can get like 99% of your base .Net code (excluding naming if it is obfuscated of course) in a single click in an app like ILSpy. That’s the same with Mono and Unity, at least for Windows (haven’t checked on other platforms, but it shouldn’t be that different, I suppose). You get a bunch of dlls when you build your game, in particular Assembly-CSharp.dll in your Data/Managed. This includes all your non editor/plugins custom classes, which means “hide yo code, hide yo data, there’s a library intruder”. If you open this dll with ILSpy, you’ll probably find all your code barely touched by Unity (they optimize stuff like loops on build time). From this point, if you want to hide something, there are two solutions:

  • hide your data inside gameobjects metadata : this gets compiled into their .assets files at build time and seems like a freaking mess to open. If your data is critical, this is probably where you want to put it.
  • hide your methods inside a non managed library and call it via dllimport : this gives another layer of protection to your code, even though it’s not impermeable. We’ll use this.

So the goal is : create a non managed dll that stocks the flag the powners have to find about, call it in our managed code and generate path in game with that data. Want to check out the challenge? Download it here (Windows only, sorry)! Let’s do a step by step on how to solve this:

  • Find out this is a Unity game : I’m handing out solution here, but during the ctf, it was not specified. There were a few hints though:
    • the exe icon is the default unity icon
    • data/Managed/ has UnityEngine.dll
    • data/Resources/ files have unity in their name
  • Open Data/Managed/Assembly-CSharp.dll with ILSpy.
  • Find the class code for HeroMove, decompile it and get the lines of the dllimport.
  • Find YeOldeContent.dll in data/Plugins/. You can try to open it in ILSpy, but you’re going to be insulted.
  • Two options here:
    • the dev way : develop a .Net app that dllimports the non managed library and get the flag
    • the hacker way : extract the static strings directly from the non managed library

Now there’s a hiccup : the flag is incomplete, you have to interpret it ingame to get the complete flag (cf. directions). There’s also another hiccup if you use the dev way : I’ve put an extra security on the dll function that requires a passkey to get the flag directly. This passkey is inside the metadata, so if you want to go hardcore, try to open the .asset files and get that passkey. Else, you’ll have to replay a famous scene from Monty Python’s Holy Grail.

That’s it, you can witness my noobitude in computer security. Anyways, it was fun to create and I’m glad that some powners actually were able to break it! Regarding game part, I’m going to have to redo it, because it’s really fucking buggy. I tried to transpose Unity2d components in a full 3d world, and it didn’t go well. I’ll make an article about that later, but it was a pretty stupid idea. I used the Dungeon tileset over at OpenGameArt on a sidenote. Really awesome art!

That being said, have fun, code safe.

Tuxic

A quick look at GLKit

Those who know or follow me should know by now I focus a lot on Microsoft tech. Not really that I only love their tech and go tell the others to fuck themselves, but I’ve had the opportunity to go into details professionally, and not much on concurrent stuff. I also specialize in 3d, that’s why you can read some stuff about that on my blog, and I’ve done a bit of MS 3d tech : XNA, DirectX/SharpDx, HLSL, Babylon.js (it’s done by my MS mentors <3 ), etc…

Anyways, once in a while, I get to do other stuff, like Polycode, or even Löve2D when I feel I need a laugh. More recently I’ve been hired on a mission involving iOS and a whole bunch of 3d stuff. I can’t really describe it, but I get to do realtime opengl on an ipad as a daily basis. That said, you might like to know I’m a total ass concerning opengl and iOS in general. I’ve got a 1st gen ipad that’s so slow we mostly use it for Spotify OH SORRY, YOU NEED iOS6 FOR THAT (ever since my Nexus 7 died out for no reason and said app shows no interest whatsoever in Windows RT (YEAH I’VE GOT A WRT TABLET, DEAL WITH IT)), and a 2009 Macbook pro that’s got a broken screen, no battery, and no charger. Soooo for the iOS part, I’m totally lacking the experience. Regarding OpenGL, I can’t say I’ve done much. Back in the days (that would be around 2006-2008) I used to fiddle with C templates in Code::blocks without having an idea of what I was actually doing. Yet, I felt like I could overcome this : I’ve seen the fires of DirectX, and have returned to say “lolnope”. So yeah, I took the mission.

Anyways, a week or so later, I can say I’m pretty surprised : GLKit is really good! Basically, GLKit is a set of helpers for OpenGL ES 2 on iOS. This includes blazing fast vector and matrix math, full integration with UIKit (iOS GUI framework), predefined constants for operations like vertex layout and base shaders that work like a charm! Of course, you still have low level gl stuff to handle, like buffer upload and manual VAO management (even though the concept of VAOs has got to be the best thing in the world), but you can setup a simple OpenGL program in not much lines of code. So yeah, GLKit gets my thumbs up. Only sad thing is that it’s exclusive to iOS, and I’d be doing a lot more of OpenGL if you could use it on other platforms. I suppose there are equivalents out there, but as always, finding time for something new is kind of a luxury nowadays.

Anyways, to show you what I mean by simplicity, let’s code a fairly simple program that outputs a quad with uniform color. If you’re an opengl/iOS expert, please insult me on twitter if I’m doing something wrong. First things first, everything included with Apple’s GLKit is prefixed with GLK, and everything that belongs to opengl directly is prefixed by gl.

We’ll start by making a new xcode Cocoa touch project, with a single view template, because the point is to show you how few lines are enough to get you doing opengl. Since I’m working exclusively for ipad, my project is not universal, so that’s up to you. Once we’ve created the project, we’ll go into the storyboard(s) and modify the base view class to GLKView. This ensures GLKit encapsulates the view to make it available as a canvas to draw on. Next, we’ll go into the ViewController.h to add a call to GLKit headers and define our controller as a GLKViewController. Your ViewController should look like this :

#import
#import

ViewController : GLKViewController

That’s all we’ll do in the header file, let’s head over to the ViewController.m ! We’ll add the most important stuff : the context, of type EAGLContext. This is the object that will bind OpenGL to our view and tell OpenGL to draw on it. So in your ViewDidLoad, you will initialize this context and attach it to the view :

ViewController
{
    EAGLContext* context;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; // context creation
    // View setup
    GLKView* view = (GLKView*)self.view;
    view.context = context;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
    [EAGLContext setCurrentContext:context];
}

You’ll notice the drawableDepthFormat in these lines. To make it simple, this is the depth format OpenGL will use for the render target, aka our view. If that’s not clear, Apple has a lot more to say about this. Now, let’s draw something! We’ll start by clear the screen with a horrible magenta color to ruin your eyes. As a reminder, the principle of clearing is to make sure you draw/render your calls on a clear frame. If you don’t do it, you’ll be drawing over the previous frame. And unless for some unknown reason this is what you are looking for, you want to clear your frame before drawing anything. It’s like an automatic background color. The color can be anything in the RGB + Alpha domain (limited by float precision in general), so you can get creative. So, we’ll start by overriding a method GLKViewController implements : -(void)glkView:(GLKView *)view drawInRect:(CGRect)rect. This convenient method is automatically called at regular intervals to draw a new frame. It’s 30 frames per second by default, and you can set this higher or lower with self.preferredFramesPerSecond in your controller. Aim for 60 FPS, your customers’ eyes will thank you. In this method, we’ll set the clear color and clear our main buffers : color and depth.

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
    glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

The glClear method takes flags with specific masks to tell the GPU to clear specific buffers. Fortunately OpenGL is provided with a whole set of defines so that you don’t have to remember these masks. You can launch your app, and you should by now be screaming “DEAR LORD MY EYES”. Don’t thank me, it’s normal.

Okay, so that was fun, what more can we do? Let’s draw something! A quad! With indices (elements in opengl, don’t ask) to make it funnier! So like I said, GLKit provides a ton of math helpers, and we’re going to take advantage of 3d vectors to define our vertices in space. We’ll also define a bunch of indices to order our draw calls and send all of this to our GPU. Let’s add all of this inside the ViewDidLoad method, right after setting our context. Here’s the code as I explain it through the comments and bellow (scroll for more) :

    GLuint vertexArray; // our VAO
    GLuint vertexBuffer; // our VBO for vertices
    GLuint indexBuffer; // our VBO for indices

    GLKVector3 vertices[4];
    vertices[0] = GLKVector3Make(-0.5f, -0.5f, 0); // create a new GLKVector3 structure
    vertices[1] = GLKVector3Make(0.5f, -0.5f, 0);
    vertices[2] = GLKVector3Make(0.5f, 0.5f, 0);
    vertices[3] = GLKVector3Make(-0.5f, 0.5f, 0);
   
    GLuint indices[6];
    indices[0] = 0;
    indices[1] = 1;
    indices[2] = 2;
    indices[3] = 0;
    indices[4] = 2;
    indices[5] = 3;
   
    glGenVertexArraysOES(1, &vertexArray); // create the VAO
    glBindVertexArrayOES(vertexArray); // tell opengl we're using it
   
    // create the vertices VBO
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); // tell opengl we're using it
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // upload the date to the GPU
   
    // same story for the indices VBO
    glGenBuffers(1, &indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
   
    // tell opengl to activate position on shaders...
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    // and use this part of our vertex data as input
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLKVector3), 0);
    // close our VAO because we're done here
    glBindVertexArrayOES(0);

That’s a lot of code, but it’s pretty straightforward. The first 3 variables are identifiers to GPU buffers and the VAO, don’t worry about them now. First we create 2 arrays to store our vertex and index data. For vertices, we’re using GLKit’s implementation of a 3d vector, GLKVector3. It’s a C struct, so init is old school style with C functions. Indices use a base type of GLuint which is an alias for a platform unsigned integer. It’s easier to read and indicates this part of your code is opengl stuff. Every lib does it in 3d anyways, so get used to these aliases. The fun part begins just after that : we create a VAO and use it. VAOs are kind of hard to explain, but basically, they’re memory addresses that act like containers to a set of buffers. So the point is, you create and bind a VAO first to set its data, and at render time, you bind it back to automatically get the buffers you defined in it. And this, kids, is why it’s awesome. This is pure opengl though, it’s present in ES 2 and recent opengl implementations for computers, so enjoy. You might notice a difference on other platforms : here we call glGenVertexArraysOES which is specific to ES 2. Just remove the OES suffix and it’ll work just fine on your computer. The point of our 3 variables at the start is that we store the identifiers for reuse (and disposal). Next, we create our index and vertex buffers GPU side and upload our data. The steps are always the same : create the buffer, tell opengl to use it as a specific buffer (using the defined masks), upload our data. The upload method takes a few parameters : the mask for which buffer we’re aiming, the size in bytes of the data we’re sending, the actual data, and its usage. Usage is how to specify how the GPU will act with the data regarding CPU : if you plan to update your vertices often, you might want this to be dynamic. That’s not the case here, so we’ll set it as static. More info on the official docs for glBufferData. This operation is exactly the same for indices and vertices, appart from their specific masks.

The next part is kind of where I consider black magic usually happens with DirectX : layout. The point of layout is to tell your GPU how to interpret the vertex data you send. In DirectX, this gets me going all “wat” as it is totally counter intuitive. OpenGL in raw is a bit better, and GLKit makes it pretty simple. So first of all, we tell OpenGL that we want position activated for our shaders with glEnableVertexAttribArray. We use a GLKit define to simplify this, so it’s clearly too easy. The tricky part is defining which part of your data is actually position. As you should have noticed, we uploaded GLKVector3 on our GPU. It’s a structure made of 3 floats, and we didn’t normalize it, and all of our vector defines the position. So when we define our data structure with glVertexAttribPointer, it’s pretty simple : first, what we are defining (position), then the number of values defining our position, the type of value (using a gl define and not an alias type), a boolean to tell if it’s normalized data, the size in bytes of 1 vertex (aka the stride, since we are in a flat array GPU side), and the offset to the start of our data in the structure we sent the GPU. That’s it (yeah, that’s already a lot of stuff). We close the VAO so that OpenGL knows we’re not writing into it anymore.

So, how do we draw? We need a shader, or else nothing will ever show on our screen. But right now, I don’t feel like writing GLSL, doing a shader program structure, compiling stuff and uploading it to the GPU, etc… fortunately, GLKit provides a helper shader that’ll do most of what you’re looking to do with a shader : GLKBaseEffect. Right after our previous code, let’s define one (make the variable on the instance level, we’re going to need it later) :

    GLKBaseEffect* effect;
    effect = [[GLKBaseEffect alloc] init]; // init our effect
    // set up a constant color to draw with
    effect.useConstantColor = GL_TRUE;
    effect.constantColor = GLKVector4Make(0, 1, 0, 1);
    // set up "camera"
    effect.transform.projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(60), fabsf(view.bounds.size.height / view.bounds.size.width), 0.1f, 100.f);
    effect.transform.modelviewMatrix = GLKMatrix4MakeTranslation(0, 0, -5);

So, initialization is easy : create an instance of the class, and have fun with the properties. There’s a ton of them, including 3 lights, texture management, diffuse, emissive, specular color, etc… we’ll just be using a constant green color for the sake of simplicity. We’ll also set up our “camera” so that we can view our render from a certain distance. We make use of another GLKit structure : GLKMatrix4. There are many helper functions to create the projection and view matrices (google it if you don’t know what it means), so basically we set our projection to a 60° FOV, with the aspect ratio of our screen, and a near/far to [0.1f, 100.f[, which is totally arbitrary. Small fact that can save you five minutes of rage : during ViewDidLoad, view’s width and height don’t take orientation in account. So if you’re in landscape like I am, invert width and height for aspect ratio math. This is fixed during runtime, so it’s just for the sake of having a perfect square on the screen for this example. So now, to draw our stuff, we’ll go back to our draw method and right after the clear order, add this:

    glBindVertexArrayOES(vertexArray); // use our VAO
    [effect prepareToDraw]; // do secret mysterious apple stuff
    glDrawElements(GL_TRIANGLES,  6, GL_UNSIGNED_INT, 0); // draw
    glBindVertexArrayOES(0); // don't use our VAO

As I said previously, loading our VAO allows us to specify to the GPU we want to use all the associated data (index and vertex buffer). We spool the effect to prepare all the shadery stuff in the back (legend wants it that shader is actually generated realtime depending on the properties used) and draw our indexed elements : first we specify what we are drawing (triangles max, no quads for ES 2, sorry), how much indices we’re reading, the kind of data the indices are, and the offset, useless thanks to the VAO. We then unbind the VAO to prevent memory leak GPU side (it’s a best practice, it doesn’t necessarily happen). Run it, and you should see some ugly green square which a magenta background burning your eyes. Success! One last thing though : unsetting all the data. Add this override to ViewDidUnload :

-(void)viewDidUnload
{
    [super viewDidUnload];
   
    // delete our buffers GPU side
    glDeleteBuffers(1, &vertexBuffer);
    glDeleteBuffers(1, &indexBuffer);
    glDeleteVertexArraysOES(1, &vertexArray);
    // delete our context
    [EAGLContext setCurrentContext:context];
    if ([EAGLContext currentContext] == context)
        [EAGLContext setCurrentContext:nil];
    context = nil;
}

This is important because you need to remember OpenGL is C and not Objective-C. Meaning that resources don’t get automatically released and GPU side can keep the garbage for a long time. So save your iDevice, release OpenGL stuff.

Well, that’s it. It might seem like a lot of code, but if I showed you the same thing with DirectX, you’d be screaming most probably. Anyways, this is just an introduction, and it covers approximately nothing of what kind of benefits GLKit brings. It’s really a great piece of code for fast app development, and the great part is that you don’t have to use it if you don’t want : it’s pure helper over OpenGL ES 2, and sweetens the stuff without making it dependant! I’d recommend you have a look at Jeff Lamarche’s code if you want to get started and also the book “Learning OpenGL ES for iOS” which is an excellent way to go way deeper into this tech.

You can find the full code for ViewController.m on this Gist !

Have fun, code safe.

Tuxic

Unity : metronome like a pro

I’ll be honest : after yesterday’s rant, I really thought about if I should sell you this code through the asset store or not. But hey, I’m not such a bitch, the trick’s pretty simple.

So here’s a nice way to get an acceptably precise metronome, with custom BPM and signature. The purpose is to create a MonoBehavior that you can stick to an entity to count your beats. Let’s start by creating a new C# script (javascript should be straight forward, but I don’t use it, sorry). I named it metronome, because that’s what it is. We’ll add in a few fields that will make sense soon enough :

public int Base;
public int Step;
public float BPM;
public int CurrentStep = 1;
public int CurrentMeasure;

private float interval;
private float nextTime;

First 3 fields should be straightforward if you know a little bit of music theory : signature represented by its base and step amount, and Beats Per Minute. CurrentStep and CurrentMeasure just let us keep track of what step/measure we’re on. Now this is where the trick starts in order to be as precise as possible : interval is the absolute amount of seconds there should be between 2 beats. nextTime is the relative moment of when the beat will actually occur.

I see the guys in the back of the room going all “WTF man”, but it’ll make sense in a second : we are going to use Unity Coroutines. Unity uses Mono, which supports a great load of C# thread operations, including Tasks. The problem is, Unity is not thread safe, and tends to go all “NOPENOPENOPE” when you use threads and Unity objects. This is were the coroutines come in : they are a sort of bastard “multitask” technique that consist in watering down heavy operations between frames. That’s the important word : frame. Basically, a coroutine is a yield return method that disperses its executions on a frame to frame basis. On its simplest form, it works much like a simple component update, as launched coroutines are each called by default once per frame until they are over. The interesting part is the kind of value you can send to your yield return.

UnityGems did a great article on coroutines, and this is what you can send as a return value (shameless copy from their article) :

  • null – the coroutine executes the next time that it is eligible
  • WaitForEndOfFrame – the coroutine executes on the frame, after all of the rendering and GUI is complete
  • WaitForFixedUpdate – causes this coroutine to execute at the next physics step, after all physics is calculated
  • WaitForSeconds – causes the coroutine not to execute for a given game time period
  • WWW – waits for a web request to complete (resumes as if WaitForSeconds or null)
  • Another coroutine – in which case the new coroutine will run to completion before the yielder is resumed

I highlighted the one we are going to enjoy very much : WaitForSeconds. It’s straightforward, give it an amount of time and it will execute when that time is consumed. Let’s write a first coroutine with that!

    IEnumerator DoTick() // yield methods return IEnumerator
    {
        for (; ; )
        {
            Debug.Log("bop");
            // do something with this beat
            yield return WaitForSeconds(interval); // wait interval seconds before next beat
            CurrentStep++;
            if (CurrentStep > Step)
            {
                CurrentStep = 1;
                CurrentMeasure++;
            }
        }
    }

Simple coroutine : infinite loop that increments CurrentStep and CurrentMeasure. It works pretty fine, but the more discerning readers will have noticed that we never set interval. I’m going to do a simple public method for that, to be able to reset and change my coroutine :

    public void StartMetronome()
    {
        StopCoroutine("DoTick"); // stop any existing coroutine of the metronome
        CurrentStep = 1; // start at first step of new measure
        var multiplier = Base / 4f; // base time division in music is the quarter note, which is signature base 4, so we get a multiplier based on that
        var tmpInterval = 60f / BPM; // this is a basic inverse proportion operation where 60BPM at signature base 4 is 1 second/beat so x BPM is ((60 * 1 ) / x) seconds/beat
        interval = tmpInterval / multiplier; // final interval is modified by multiplier
        StartCoroutine("DoTick"); // start the fun
    }

This goes a bit more into music theory, but I suppose you can deal with that if you’ve read this far. So we get the absolute interval between each beat and store it in our field. You’ll notice I use StartCoroutine and StopCoroutine with a string of the coroutine method name. This method is more expensive but allows us to stop the coroutine at will, which is appreciable. You can call StartMetronome() in your Start(), create an entity and attach the script as a component, and set for example Base and Step to 4, BPM to 120 and launch. In your debug log, you’ll have a nice timed “bop” appearing in an endless loop. Mission accomplished.

Wait, we still have something to fix : on usage you’ll realize that this is precise but not enough. It tends to desynchronize pretty fast (at 120bpm, it’s be off tracks in less than 4 measures) and that’s bad if for instance you’re making a musical game. The reason is simple : coroutines are balanced by frames, and frames have a delta that you don’t really control. The problem is that your interval is fixed, but the WaitForSeconds might just decide that it’s too late to execute at this frame, let’s wait another one or two. Thus the wibbly wobbly bullshit the metronome outputs. This is where nextTime comes in. The purpose is to resync the metronome with effective time scales. The wait interval will thus never be constant. Let’s modify our methods :

    public void StartMetronome()
    {
        StopCoroutine("DoTick");
        CurrentStep = 1;
        var multiplier = Base / 4f;
        var tmpInterval = 60f / BPM;
        interval = tmpInterval / multiplier;
        nextTime = Time.time; // set the relative time to now
        StartCoroutine("DoTick");
    }

    IEnumerator DoTick() // yield methods return IEnumerator
    {
        for (; ; )
        {
            Debug.Log("bop");
            // do something with this beat
            nextTime += interval; // add interval to our relative time
            yield return WaitForSeconds(nextTime - Time.time); // wait for the difference delta between now and expected next time of hit
            CurrentStep++;
            if (CurrentStep > Step)
            {
                CurrentStep = 1;
                CurrentMeasure++;
            }
        }
    }

This very simple trick allows you to fix this sync problem, as the wait delta will be fixed depending on actual time and expected time. Of course, this is far from perfect, but it does the trick : beats are really precise, even after 20 minutes of play. The rest is up to you. I decided to implement events on tick and on new measure, and you can find my code sample on this gist. Output is as follows with a visual thingy:

Anyways, have fun, code safe.

Tuxic

Unity2D : hail to the king, baby!

So yeah, like I previously stated on the blog, I’ve been testing Unity2D a lot these past days (and a bunch of other stuff, as always).

Overall impression is “GUDDAMITFINALY!1!!!11!”. And Unity delivers. So in the past I wasn’t the first Unity3D supporter, on the main purpose that 3D is not a subject to be treaded lightly, and a hell load of noobs and idiots would start making stuff with the free version. Eventually I got to work a lot with it this year and changed my mind concerning its raw power. I mean, just look at the time I lost on Kerbal Space Program, and this marvel of procrastination is being made with Unity. And workflow is really great, their Entity Component system is awesome. Always had problems dealing with Monodev, but as a MS tech dude, I redirected every single code line to VS. And I frantically never touched a line of Javascript. Still have to do some progress on my problems with this language, and Unity’s implementation is just… weird.

One of the things I’ve always regretted with Unity was the absence of real 2D support. It was until now a 3D tool, and you’d have to hack it to get things to show up in 2D. And the fucking asset store taking advantage of that : no sir, I’m not paying 60 bucks to show sprites on a free game making tool. So being limited to 3D is kind of drastic. Like I said, 3D is hard, people expect so much from it, you can’t just go around making 3D stuff without having previous experiences. Stuff like shaders, LOD and animations just give the creep to any dev that knows, and despite Unity3D being a very well conceived tool, you won’t escape these matters. And god I hate the asset store. This thing is evil. This thing should be held responsible for all the crap shitty mobile devs create. I’m exagerating of course, I just have a problem with these guys saying “oh, Unity doesn’t do that? Let’s go waste $150 on a plugin/asset/code library!” when it’s something as simple as post process shaders or block level design.

Alright, let’s stop ranting for a second.

To sum it up, Unity2D is Unity3D with one dimension less. This means you’ve got SpriteRenderer instead of MeshRenderer, that you’ve got 2D prefabs, 2D physics, 2D post process, 2D goodness! It’s freaking awesome, seriously. I’ve never tried other 2D alternatives like GameMaker, but I suppose they offer the same type of pleasure Unity2D sends your way. Drag&drop your sprites, add 2 or 3 entities, and you’ve got yourself a working prototype. The fabulous idea to natively support spritesheets and atlas textures is just enormous and fantastic, and the animation workflow is fan-tas-tic. Going back to physics, I was really impressed they were able to keep almost all of their 3D conventions, with the ease and simplicity it procured. Of course, basic primitive shapes like rectangles and ellipses are available, but the sprite based collider is art. Creating custom colliders has never been this simple! The greatest thing of this all will remain their 3D/2D mixing : a 2D scene is just an orthographic camera with a bunch of 2D components, but still in a 3D scene. The point is, you can easily merge 3D elements into a 2D scene, and the contrary too, because nothing stops you from using a SpriteRenderer in a 3D Scene.

So to try it out, I recreated the core gameplay of my SpaceShooterz game, and this took me.. at most something like half an hour : background parallax, player spritesheet, enemy + basic move routine, shooting and killing. 30 freaking minutes, and not even trying hard.

So this is great news for indie devs. We get an awesome tool for free and the raw power to create very complex 2D gameplays in no time. Since Unity exposes free exports to iOS and Android now, including the long-awaited Windows Phone and Windows 8, you devs have no excuse! Go make some games! This comes at a cost of course : Unity is heavy. In the last year only, the package went from 400megs to a whole freaking gig. The interface also is a marvelous work of the kraken, but you can get over that. I would recommend a computer with good perfs and a big screen though, your eyes will thank you.

Anyways, have fun!

Tuxic

Unity 2D in progress

Been testing out Unity3D’s new 2D features on the 4.3 update, I’ve got to say I’m quite impressed by the simplicity of the overall thing. Blogging on it really soon!

In the meantime, have a dogemon

Polycode Visual Studio setup

Setting up a Polycode project in Visual Studio is a royal pain in the ass. The fact that you have to use a Win32 project is the main reason. We can resume this in two dreaded words : HUNGARIAN NOTATION. God I hate this.

Of course, this is just for the entry point and fortunately, once this is done, you won’t have to face those horrible names in your code (unless you like this, which should be considered scary). Anyways, here’s a step by step on how to setup a basic Visual Studio project and get you running on trully interesting code in no time:

  1. First of all, we’re going to need a VC++ Win32 project. We’re going to make it empty (screw you, precompiled headers) so that we don’t get a load of files that we won’t need later
  2. We’ve got our neat empty project and I’m going to assume that you’ve got a release build of Polycode. The path for this example will be “C:\Polycode\Framework”. We’re going to go into project properties for our project and set your configuration to “All Configurations”
  3. Go to C/C++ > General and Edit on “Additional Include Directories”. Add the following folders
    • C:\Polycode\Framework\Core\include
    • C:\Polycode\Framework\Core\Dependencies\include
    • C:\Polycode\Framework\Core\Dependencies\include\AL
  4. Go to Linker > General and Edit on “Additional Library Directories”. Add the following folders
    • C:\Polycode\Framework\Core\lib
    • C:\Polycode\Framework\Core\Dependencies\lib
  5. Go to Linker > Input, Edit on “Additional Dependencies” and add the following after setting the Configuration to the correct value
    • For Debug Configuration :
      Polycore_d.lib
      zlibd.lib
      freetype_d.lib
      liboggd.lib
      libvorbisd.lib
      libvorbisfiled.lib
      OpenAL32d.lib
      physfsd.lib
      libpng15_staticd.lib
      opengl32.lib
      glu32.lib
      winmm.lib
      ws2_32.lib
    • For Release Configuration :
      Polycore.lib
      zlib.lib
      freetype.lib
      libogg.lib
      libvorbis.lib
      libvorbisfile.lib
      OpenAL32.lib
      physfs.lib
      libpng15_static.lib
      opengl32.lib
      glu32.lib
      winmm.lib
      ws2_32.lib
  6. Back in “All Configurations”, go to Build Events > Post-Build Event and Edit “Command Line” to add following command
    if not exist "$(ProjectDir)default.pak" copy "C:\Polycode\Framework\Core\Assets\default.pak" "$(ProjectDir)"

    if "$(ConfigurationName)" == "Debug" (
      if not exist "$(TargetDir)OpenAL32d.dll" copy "C:\Polycode\Framework\Core\Dependencies\bin\OpenAL32d.dll" "$(TargetDir)"
    ) else (
        if not exist "$(TargetDir)OpenAL32.dll" copy "C:\Polycode\Framework\Core\Dependencies\bin\OpenAL32.dll" "$(TargetDir)"
    )

    What this does is it copies to build directory the OpenAL dlls so that the sound module runs correctly. Polycode author Ivan Safrin recently spoke about removing it for a more low level sound API, so keep that in mind for the future. This also adds the default.pak file to the project, which is not an obligation, but it contains starter resources to get you up and running a Polycode app directly, like fonts, default shaders, textures, stuff like that.

  7. We’re normally ready to code! Let’s add a file. I’ll name it main.cpp, because I like simple stuff, and if we could keep this file simple, it would be great. Anyways, let’s fill it with our entry point, that is, ugly Win32 code :
    #include
    #include "windows.h"
    #include "PolyApp.h"

    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
        PolycodeView *view = new PolycodeView(hInstance, nCmdShow, L"My polycode app");
        PolyApp *app = new PolyApp(view);

        MSG Msg;
        do {
            if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) {
                TranslateMessage(&Msg);
                DispatchMessage(&Msg);
            }
        } while (app->Update());

        delete app;
        delete view;

        return Msg.wParam;
    }

    So this is where your creativity comes in. Following the main wiki, you’re going to create an entry class (here, it’s called PolyApp) that is polled by the Win32 API for events (the do/while part) until you decide to shut it down. Protip : if you plan on doing something cross-platform, use the POLYCODE_CORE define that is defined at build depending on OS. You’re better off that way.

  8. Have fun with Polycode

So that’s it, don’t forget to change your Polycode build path, and you should have a project running. Hit me up on if something’s wrong!

Tuxic