Afficher des sprites et des BOBs sur Amiga OCS et AGA (2/2)

Cet article est le second – et donc dernier – d'une série de deux consacrée à l'affichage de bitmaps sur Amiga. Dans le premier article, nous avons exploré dans le détail les sprites du hardware. A cette occasion, il est apparu que les sprites sont comme les hobbits : pratiques et colorés, mais petits et peu nombreux. Et même si le hardware permet d'en démultiplier apparemment le nombre en les découpant ou en les répétant, recourir à ces astuces reste assez contraignant.
C'est pourquoi une autre solution a souvent été préférée pour afficher des bitmaps : les BOBs. Le BOB est un bitmap affiché à l'aide du Blitter, le coprocesseur dont la fonctionnalité la plus notoire est la copie des données d'une ou plusieurs zones de mémoire vers une autre.
Des vector balls (avec quelques droites pour mieux constater la 3D)
Comment afficher un BOB ? Et ne faut-il pas alors assurer soi-même toutes ces tâches qui étaient prises en charge automatiquement par le hardware s'agissant de sprites : transparence, recover, clipping, détection de collisions, etc ? Tout cela et plus encore dans ce qui suit.
Mise à jour du 05/08/2018 : Précision apportée sur la nécessité d'utiliser b (l'inverse du masque) et non B (le masque) comme source dans la combinaison logique utilisée par le Blitter.
Mise à jour du 11/08/2018 : Ajout de perfectBob.s dans l'archive, une version améliorée de bobRAWB.s où la partie rectangulaire du décor que le BOB recouvre est précisément ou globalement restaurée au Blitter.
Mise à jour du 14/08/2018 : Mise à jour de bobRAW.s et bobRAWB.s dans l'archive, car les versions proposées ne mettaient pas en oeuvre le masquage présenté !
Mise à jour du 01/10/2018 : Tous les sources ont été modifiés pour intégrer une section "StingRay's stuff" qui permet d'assurer le bon fonctionnement sur tous les modèles d'Amiga, notamment dotés d'une carte graphique.
Continuer la lecture de "Afficher des sprites et des BOBs sur Amiga OCS et AGA (2/2)"
Afficher des sprites et des BOBs sur Amiga OCS et AGA (2/2)

Afficher des sprites et des BOBs sur Amiga OCS et AGA (1/2)

Quoi de plus confortable qu'un sprite ? Le coprocesseur graphique l'affiche en laissant voir le décor derrière ses pixels transparents, et il préserve le décor derrière ses autres pixels pour le restaurer quand le sprite est déplacé. Par ailleurs, il découpe le sprite s'il sort de l'écran.
Malheureusement, les capacités de l'Amiga 500 sont en la matière très limitées. Huit sprites de 16 pixels de large, même de hauteur infinie, en 4 couleurs dont une transparente, seulement ? C'est la dèche...
Les sprites n'en conservent pas moins une certaine utilité, à condition d'en utiliser pleinement le potentiel. Ainsi, il est possible de les attacher pour former jusqu'à un bitmap de 64 pixels de large, de hauteur infinie, en 16 couleurs dont une transparente, notamment. Ou alors, il est possible d'en réutiliser pour créer un playfield supplémentaire, dont le contenu devra toutefois être un motif répétitif qui, dans le meilleur des cas, occupera 48 pixels de large sur une hauteur infinie, en peu de couleurs. Par ailleurs, l'Advanced Graphics Architecture, dont l'Amiga 1200 est doté, dispose de fonctionnalités un peu étendues en matière de sprites. En particulier, leur largeur unitaire passe de 16 à 64 pixels.
Des sprites un peu plus mieux en AGA
Comment afficher des sprites ? Et utiliser les sprites pour afficher un gros et beau bitmap, ou un playfield supplémentaire ? Et enfin utiliser les sprites sur AGA, sachant que Commodore n'a jamais documenté ce hardware ? Tout cela et plus en encore dans ce premier article consacré à l'affichage de bitmaps sur Amiga OCS et AGA.
Mise à jour du 08/07/2018 : Correction d'un bogue dans triplePlayfield.s.
Mise à jour du 01/10/2018 : Tous les sources ont été modifiés pour intégrer une section "StingRay's stuff" qui permet d'assurer le bon fonctionnement sur tous les modèles d'Amiga, notamment dotés d'une carte graphique.
Continuer la lecture de "Afficher des sprites et des BOBs sur Amiga OCS et AGA (1/2)"
Afficher des sprites et des BOBs sur Amiga OCS et AGA (1/2)

Les opérateurs étoile (* et **) en Python

En Python, chacun sait que l'opérateur * permet d'effectuer une multiplication sur des opérandes numériques, ou à répéter un opérande quelconque, tandis que l'opérateur ** permet d'effectuer une élévation à une puissance quelconque d'un opérande numérique :
print (2*3)
print (2*'Hello, world!')
print (2**3)
6
Hello, world!Hello, world!
8
Ce qui est moins connu, car elle est assez mal documentée, c'est la possibilité d'utiliser ces opérateurs pour du déballage (unpacking) d'itérables divers en vue de constituer un autre itérable. Par exemple :
x = ['A', 'B']
y = ('C', 'D')
z = [*x, *y]
print (z)
['A', 'B', 'C', 'D']
Comment est-il possible d'utiliser ces opérateurs de cette manière ? Et pour quoi faire ? L'exploration de la documentation de Python permet de constater qu'ils peuvent servir dans deux circonstances : pour créer des itérables, et pour fournir des arguments à une fonction. Explications...
Mise à jour du 19/05/2018 : Mention de notations supplémentaires pour créer un itérable à partir d'un autre.
Continuer la lecture de "Les opérateurs étoile (* et **) en Python"
Les opérateurs étoile (* et **) en Python

Fessebouc, l’Internet des neuneus ?

L'affaire Cambridge Analytica se définit avant tout par l'empressement avec lequel les médias mainstream ont communiqué sur la question de la propriété des données personnelles, contribuant à la constituer en problème auquel les pouvoirs publics sont invités à apporter sur le champ une solution.
Facebook, the leaking ship
L'histoire dira si cette affaire est le scandale qu'on prétend.
Dans sa version de base, des universitaires pervertis par l'appât du gain auraient siphoné les comptes de millions d'utilisateurs de Fessebouc au moyen d'un subterfuge, puis utilisé ces données pour déterminer le message à tenir selon le subconscient d'électeurs, lequel moyen aurait permis de piloter la campagne d'un démagogue, ce qui aurait déterminé l'élection de ce dernier au poste de leader du monde libre. Naufrage de l'Humanité.
Comme on le voit en la présentant ainsi, l'histoire tient du récit mythologique. C'est les hommes précipités dans le malheur par ceux d'entre eux qui ont accédé au moyen de les agir comme des dieux.
Mise à jour du 06/04/2018 : Découvrant ici (via l'excellent Hacker News) que l'université de Berkeley propose gratuitement un cours de Data Science (Data 8X) aux profanes, je le recommande à ceux qui voudraient faire l'effort de s'instruire.
Mise à jour du 17/04/2018 : Découvrant ici que Fessebouc-émissaire est désormais chargé de tous les maux d'Internet car il est solvable, je rajoute un petite section sur les précautions à prendre par l'internaute lambda pour protéger un peu sa vie privée quand il navigue sur le Web.
Mise à jour du 15/08/2018 : Ajout de Decentraleyes au rang des extensions à installer.
Mise à jour du 14/03/2020 : A partir de la version 74, ceux qui utilisent Firefox seront invités à installer l'extension Facebook Container. A défaut de prendre les précautions prodiguées ici, c'est toujours ça de pris.
Mise à jour du 16/01/23 : Après des tests, il s'avère que l'extension Forget Me Not nettoie bien mieux les donnnées que Cookie AutoDelete et doit donc être recommandé en lieu et place.
Continuer la lecture de "Fessebouc, l’Internet des neuneus ?"
Fessebouc, l’Internet des neuneus ?

Calculer la matrice de projection de WebGL

Tout développeur qui s'initie à la 3D avec WebGL est rapidement confronté à une entité mathématique, la matrice de projection :
[ Xe Ye Ze 1 ] x [ 2NR-L 0 0 0 0 2NT-B 0 0 R+LR-L T+BT-B F+NN-F -1 0 0 2FNN-F 0 ]
Les différentes constantes utilisées pour définir le volume de clipping se présentant par exemple ainsi (coupe Y/Z) :
Pyramide tronquée de clipping dans WebGL
Cette matrice peut sembler d'autant plus étrange au développeur qu'elle comporte 4 lignes et 4 colonnes (une matrice 4x4), alors qu'il semblerait que l'on puisse se contenter d'une matrice 3x3 pour réaliser les calculs. D'ailleurs, où est passée l'intervention de Ze au dénominateur dans les calculs ?
Bref, pourquoi cette matrice ? Comment calculer ses coefficients ? Et comment en déduire les coordonnées de la projection d'un point ?
Continuer la lecture de "Calculer la matrice de projection de WebGL"
Calculer la matrice de projection de WebGL

Les références en PHP sont-elles des pointeurs en C/C++ ?

Les références en PHP peuvent sembler assez déroutantes au développeur C/C++. S'agit-il de pointeurs ? La documentation de PHP prétend que non, mais la lecture des commentaires qui y ont été annexés laisse sur une impression bien moins catégorique.
En fait, tout dépend d'où l'on se place : veut-on chercher à comprendre comment les références fonctionnent, ou veut-on simplement déjà parvenir à décrypter le code où il en figure ?
Quelle que soit la manière dont les références fonctionnent réellement, ce qui sème le trouve dans l'esprit du développeur C/C++, c'est qu'il semble que ces références ne sont pas des pointeurs, du fait de la syntaxe.
En effet, soit le code C++ suivant :
int i, *p;
i = 0;
p = &i;
std::cout << *p;	// On écrit *p et non p (comme on a écrit i)
Le code équivalent en PHP serait :
$i = 0;
$p = &$i;
echo ($p);	// Surprise! on écrit $p comme on a écrit $i
Alors, comment le développeur C/C++ doit-il décrypter les références aux références dans le code PHP ? L'objet de cet article est d'éclairer sa lanterne. Plus généralement, tous ceux qui souhaitent utiliser des références en PHP devraient trouver un intérêt à le lire - tout particulièrement pour clarifier la relation critique entre référence et unset ().
Click here to read this article in english.
Continuer la lecture de "Les références en PHP sont-elles des pointeurs en C/C++ ?"
Les références en PHP sont-elles des pointeurs en C/C++ ?

Utiliser les espaces de noms en PHP

Les espaces de noms sont apparus avec PHP 5.3.0.
Comme dans tout langage moderne, on retrouve cette notion fondamentale puisqu'elle conduit à voir tout ce qui est déclaré non pas d'abord comme une instruction, une variable, un type, ou autre, mais comme quelque chose qui peut être adressé par un nom au sein d'une hiérarchie d'espaces de noms. Autrement dit, avant la déclaration de quelque chose, il y a la définition du nom par lequel on l'adresse. L'idée est de pouvoir éviter des collisions de noms entre factorisations sans avoir à recourir à des noms à rallonge (du fait de préfixes et/ou d'enchâssements).
Typiquement, plutôt que... :
const _Zoo_Birds_TGE = "The Great Eagle";
...pouvoir se contenter de... :
namespace Zoo\Birds;
const THE_GREAT_EAGLE = "The Great Eagle";
...pour pouvoir écrire :
echo (Zoo\Birds\THE_GREAT_EAGLE);
Comme toujours, le point de vigilance est que l'association entre la hiérarchie des fichiers et la hiérarchie des espaces de noms n'est qu'un cas particulier. Dans le cas de PHP, c'est encore plus clair qu'en Python ou en Java. En effet, il n'existe pas d'équivalent à import de Java ou de Python, qui ferait à la fois le travail de require () (inclusion du fichier et intégration des éventuels espaces de noms qui sont définis à l'arborescence des espaces de noms courante) et de use (création d'alias pour les espace de noms ainsi intégrés). D'ailleurs, PHP permet même de répartir le contenu d'un espace de noms entre plusieurs fichiers !
On peut contester l'utilité du concept. Dans un échange critique sur Stack Overflow, un contributeur prétend y voir une manifestation du culte du cargo en programmation. Intéressant, même si pour un anthropologue, cela peut sembler comme une réappropriation d'un concept assez douteuse - il vaudrait mieux parler de syndrome du singe savant, déjà évoqué ici.
Voyons voir dans le détail comment utiliser cette fonctionnalité...
Mise à jour du 14/03/2018 : Mention à ::class

Continuer la lecture de "Utiliser les espaces de noms en PHP"

Utiliser les espaces de noms en PHP

Syntaxes avancées (car ramassées) en Python

Il y a mille manières d'exprimer ce qu'on désire en langage naturel, et il en va de même avec un langage de programmation.
Certaines fomulations peuvent être clairement plus laconiques que d'autres, et d'aucuns considèrent que c'est démontrer sa maîtrise du langage que de les maîtriser. Toutefois, si jouer à ce petit jeu de la syntaxe ramassée permet d'économiser sur l'écriture, il ne permet certainement pas d'économiser sur la lecture, du moins tant que celui qui doit lire n'a pas appris à écrire pareillement.
Pour aider dans cet apprentissage, cet article évolutif se propose de recenser les syntaxes ramassées qu'un développeur peut rencontrer en lisant du code en Python (version 3.6.4), à condition qu'elles présentent une véritable utilité.
Pour l'heure, on trouvera des explications suivantes... :
L'article sera enrichi au fil des découvertes réalisées au fil de lectures. Ces mises à jour seront signalées.
Mise à jour du 27/04/2020 : Sur signalement de no_one, correction d'une coquille dans un usage fréquent du slicing.
Mise à jour du 09/04/2020 : Sur recommandation de Tchich, mention à l'utilisation de zip () pour extraire les colonnes d'un tableau.
Mise à jour du 08/03/2018 :
  • rappel de la typologie (et corrections !) ;
  • extraire une plage d'éléments d'une séquence (slicing).
Continuer la lecture de "Syntaxes avancées (car ramassées) en Python"
Syntaxes avancées (car ramassées) en Python

Paramètres et décorateurs de fonction en Python

Python permet d'écrire des fonctions comportant de nombreux paramètres qui peuvent avoir des mines des plus patibulaire, surtout si elles sont par ailleurs assorties de décorateurs. Par exemple :
def g (h):
	def k (prompt, *words, **complements):
		if complements['computer'] == 'Atari':
			complements['computer'] = 'Amiga'
		h (prompt, *words, **complements)
	return k
@g
def f (prompt, *words, **complements):
	for key, value in complements.items ():
		print (prompt + ':', ' '.join (words), value)
f ('HAL speaking', 'I', 'love', 'the', computer='Atari', drink='coffee')
HAL speaking: I love the Amiga
HAL speaking: I love the coffee
Il est important de ne pas se laisser abuser par cette apparente complexité. Maîtriser les différentes catégories de paramètres qu'il est possible d'utiliser est essentiel pour exploiter le potentiel de l'écriture de fonctions en Python au quotidien. Quant aux décorateurs, il est sans doute bien moins fréquent d'y avoir recours, mais comme ils peuvent se rencontrer, il est bon de savoir commment ils fonctionnent.
Continuer la lecture de "Paramètres et décorateurs de fonction en Python"
Paramètres et décorateurs de fonction en Python

Comment marche réellement la fonction super () de Python

La méthode super () de Python a inspiré un bon nombre d'explications. Toutefois, il apparaît qu'aussi sophistiquées qu'elles soient, elles sont toutes désespérément superficielles.
Je ne parle pas de celles qui le sont d'évidence, comme cette vidéo. L'auteur est bien gentil, mais sa présentation de super() se limite à assimiler la fonction à un moyen de déléguer un appel à la méthode __init__ () (par ailleurs, tout à fait improprement assimilée à un constructeur, comme si __new__ () n'existait pas...) surchargée dans une classe C à sa version dans une classe parent A. Autrement dit, à appeler A.__init__ () depuis C.__init__ (). Mais dans l'exemple, C hérite non seulement de A, mais aussi de B. Dès lors, les questions des commentateurs fusent : pourquoi B.__init__ () n'est-elle pas appelée ? Sincèrement, avant de publier une explication sur un sujet technique, son auteur devrait s'assurer qu'il maîtrise son sujet. Comme il le dit, "The super keyword is a little bit confusing in Python. It's been confusing for decades now and it's going to continue to be confusing as we move into the future. It's just something that's confusing". Tu m'étonnes! surtout après avoir entendu sa prétendue explication...
Non. Je parle d'explications d'auteurs qui ont pignon sur rue, comme Python's super() considered super! de Raymond Hettinger, à laquelle renvoie la documentation de super(), ou encore celle d'Alex Martelli, Anna Ravenscroft et Steve Holden dans leur Python in a Nutshell. Le moins qu'on puisse dire, c'est qu'on ne ressort pas illuminé de ces lectures. Sans doute, on comprend que super() permet de jouer avec le Method Resolution Order (MRO), mais quant à savoir exactement comment, c'est une autre affaire. Tout le monde se contente de terminer en recommandant d'utiliser systématiquement super() à tous les niveaux la hiérarchie des appels, et pour le reste renvoie sur l'algorithme C3, présenté comme abscons.
Bref, tout comme peu de personnes semblent avoir compris que JavaScript est un langage orienté objet à base de prototypes (et non de classes !), y'en a-t-il seulement qui ont compris comment la fonction super() de Python fonctionne vraiment ? Sérieusement, il y a de quoi nourrir de sérieuses inquiétudes quant au niveau d'exigence des développeurs désormais. Plus personne ne se donne la peine d'aller au fond des choses, ou quoi ?
On va donc arrêter de plaisanter, et expliquer sérieusement...
Continuer la lecture de "Comment marche réellement la fonction super () de Python"
Comment marche réellement la fonction super () de Python