Oui c'est ça, comme il n'y a pas de fonction de temporisation (sur Ti 82 et 83+ en tout cas) j'ai trouvé ce calcul qui est asser long (et a partir de 70 la calculatrice renvoie un erreur parce que pas asser de mémoire)
Quel est le sens de defparameter, par rapport à un setf ou autre setq ? (j'ai testé vite fait l'effet de la macro avec macroexpand, mais je comprends rien)
Il y a la même différence entre defparameter et setf qu'entre int i; et i = 42; en C. La différence, c'est que les déclarations de variables ne sont pas obligatoires en Common Lisp.
Pourquoi as tu séparé les fonctions pour chaque oeil, alors qu'elles semblent faire pareil toutes les deux ? Suffit de mettre le random dans la fonction direct.
Parce que la fonction qui dessine l'invader est appelée à chaque frame... Si je mets le random direct dans la fonction, les yeux vont être regénérés aléatoirement à chaque frame. Ce n'est pas le comportement voulu.
J'ai pas compris l'histoire du with.
En fait, (with-sdl-init blablabla) est équivalent à (sdl-init) blablabla (sdl-quit).
Sinon, la syntaxe avec ':', c'est une histoire de packages, c'est ça ?
Il y a des subtilités que je ne maîtrise pas avec ':', mais ça sert à ça, oui. Si je fais un package bidule, et qu'il contient une fonction foo, alors je peux m'y référer avec bidule:foo. Un peu comme un '::' en C++.
Sinon, perso, j'ai des sérieux problèmes avec loop, la page de l'hyperspec est carrément imbuvable, c'est sympa de voir que ça peut s'utiliser aussi simplement
L'HyperSpec est trop hard pour commencer. Prends-toi le bouquin en ligne de gigamonkeys, ou « succesful lisp », ou un autre ; normalment, tout bon bouquin de lisp aura un chapitre sur loop.
J'ai bien aimé l'histoire des symboles que tu appelles comme des fonction.
C'est ma bidouille principale pour le moment.
Common Lisp, le retour de la vengence
Tout d'abord, le code. Ceux qui ont lu mon code précédent y verront quelques similitudes... Je vous conseille de le lire si vous le n'avez pas fait ; je ne donnerai ici que les explications sur ce qui diffère par rapport à la v1.
(ql:quickload :lispbuilder-sdl)
(in-package sdl)
(defmacro draw-tile (x y col)
`(draw-box-* (* 20 ,x) (* 20 ,y) 18 18 :color ,col))
(defun ░ (i j) ())
(defun █ (i j) (draw-tile (+ *x* i) (+ *y* j) *col*))
(defun ◉ (i j) (draw-tile (+ *x* i) (+ *y* j *eye1*) *black*))
(defun ◕ (i j) (draw-tile (+ *x* i) (+ *y* j *eye2*) *black*))
(rand-inv (defun rand-inv (f)
(setf *t* 0)
(setf *x* (random 20))
(setf *y* (random 20))
(setf *eye1* (random 2))
(setf *eye2* (random 2))
(setf *col* (color :r (random 255) :g (random 255) :b (random 255)))))
(defun draw-invader () "((░ ░ █ ░ █ ░ ░)
(░ █ █ █ █ █ ░)
(░ █ ◕ █ ◉ █ ░)
(░ █ ░ █ ░ █ ░)
(█ █ █ █ █ █ █)
(█ ░ █ ░ █ ░ █))"
(loop for l in (read-from-string (documentation 'draw-invader 'function))
for j from 0 do
(loop for e in l
for i from 0 do (funcall e i j))))
(with-init ()
(window 600 600)
(rand-inv nil)
(with-events ()
(:quit-event () T)
(:idle () (incf *t*)
(when (= *t* 50) (rand-inv #'rand-inv))
(clear-display *white*)
(draw-invader)
(update-display))))
La première ligne charge la SDL, rien de nouveau de ce côté-là. La deuxième ligne nous place dans le package SDL, ce qui a plusieurs conséquences :
je n'ai plus besoin de mettre des sdl: partout ;
toutes les fonctions et variables que je définis sont réputées faire partie de la bibliothèque SDL.
Ça prendrait deux lignes de faire mon propre package qui utilserait la SDL, ce qui serait bien plus propre... Il est donc inutilement compliqué d'étendre la SDL.
Ensuite, draw-tile a été transformée : elle est devenu une macro (plutôt qu'une fonction). Ceci signifie qu'elle sera évaluée au moment de la compilation (et non de l'exécution) : chaque fois que le compilateur croisera (draw-tile 1 2 3), il le remplacera par l'expression (draw-box-* (* 20 ,x) (* 20 ,y) 18 18 :color ,col), en remplaçant ,x, ,y et ,col par leurs valeurs. Si vous faites du C, il se passe la même chose qu'avec #define. Notez toutefois que les macros sont infiniment plus puissantes que les define, puisqu'elles permettent de disposer d'un interpréteur lisp pendant la compilation et de s'en servir pour construire toutes sortes d'expressions.
Les définitions des fonctions aux noms bizarres ne changent pas.
La fonction rand-inv ne change pas non-plus, à une exception près : une nouvelle variable *t* est crée. Elle servira à gérer le temps. Notez que T, tout court, correspond à la valeur « true » en common lisp.
La fonction draw-invader change légèrement : le space-invader n'est plus défini comme une variable, il est dans la docstring de la fonction ! Pour ceux qui ne connaissent pas, les docstrings sont des chaînes de caractères que l'on peut associer aux fonctions pour obtenir de l'aide directement dans l'interpréteur (une idée reprise notamment par Python). Ici, la fonction draw-invader va chercher son propre docstring, le parse comme une expression lisp, puis utilise l'astuce décrite dans mon post précédent qui consiste en appeler la fonction dont le nom apparaît dans la liste (comme symbole). Ne vous y méprenez pas ; l'astuce du post précédent est toujours là, j'ai simplement rajouté une étape avant.
La boucle principale change peu : à chaque frame, on incrémente la variable *t*. Lorsqu'elle vaut 50, on tire un nouvel invader au hasard (ce qui a pour effet de remettre *t* à 0 au passage). Et voilà, l'animation est là ; tout est conforme au projet original !
Et pour ceux qui n'auraient pas un interpréteur CL avec le paquet quicklisp installé, voici des screenshots.
D'abord, le programme en train de tourner :
Ensuite, mon environnement :
La fenêtre que vous voyez à droite, derrière le space-invader, est celle de Lisp. Il est en train d'hurler des warnings parce que les bindings SDL pour Lisp utilisent des constructions obsolètes.
EDIT : la couleur de l'invader est bien aléatoire, même si elle est identique sur les screens.
- Edité par GuilOooo 5 mai 2013 à 22:30:46
J'ai déménagé sur Zeste de savoir — Ex-manager des modérateurs.
Bonjour, je trouve cette idée vraiment amusante donc j'ai voulu participer à ce petit concours !
Donc j'ai programmé un Space Invader aux yeux ronds (soyons originaux ^^), avec un effet d'ombre ou de 3D (prenez le comme vous voulez, les deux marchent) qui s'adapte à la position de l'alien. J'ai utilisé le javascript, le CSS et le HTML.
var Si = new DynamicObject("SpaceInvader");
var Ears = new DynamicObject("Oreils");
var Eyes = new DynamicObject("Yeux");
var SiObject = document.getElementById("SpaceInvader");
var Cases = document.getElementsByTagName('div');
var RightEye = document.getElementById("droit");
var LeftEye = document.getElementById("gauche");
var Body = new DynamicObject("Corps");
var TimeToWait = 0;
var DisplaceX;
var DisplaceY;
var left;
var top;
Body.blurAppearance(0.5);
Ears.blurAppearance(0.5);
var Time = 0;
Update();
function Update()
{
Shadow();
left2=SiObject.style.left.split("px")[0];
top2=SiObject.style.top.split("px")[0];
if(left2<=0 || left2 >= screen.width-380)
{
DisplaceX*=-1;
Time = 0;
TimeToWait = 50+Math.floor((Math.random()+0.05)*25);
changeColor();
changeEyesPos();
}
if(top2<=0 || top2 >= screen.height-475)
{
DisplaceY*=-1;
Time = 0;
TimeToWait = 50+Math.floor((Math.random()+0.05)*25);
changeColor();
changeEyesPos();
}
if(Time >= TimeToWait)
{
Time = 0;
TimeToWait =50+Math.floor((Math.random())*100);
DisplaceX = RandomPos();
DisplaceY = RandomPos();
changeColor();
changeEyesPos();
}
Si.DisplaceOnVector(DisplaceX, DisplaceY, true);
Time++;
setTimeout(function(){Update()},1000/24);
}
function RandomPos()
{
var pos = Math.random()*12-6;
return pos;
}
function changeColor()
{
// var index=Math.floor(Math.random()*8);
var color="rgb("+Math.floor(Math.random()*255)+","+Math.floor(Math.random()*255)+","+Math.floor(Math.random()*255)+")";
for( var i = 0;Cases.length>i;i++)
{
if(Cases[i].className=="case" || Cases[i].className == "noreil")
{
// Cases[i].style.backgroundColor = colors[index];
Cases[i].style.backgroundColor = color;
}
}
}
function changeEyesPos()
{
Eyes.blurDisappearance(0.5);
if(Math.random()>0.5)
{
RightEye.style.top="162px";
}
else
{
RightEye.style.top="108px";
}
if(Math.random()>0.5)
{
LeftEye.style.top="162px";
}
else
{
LeftEye.style.top="108px";
}
Eyes.blurAppearance(0.5);
}
function Shadow()
{
var Left = (((parseInt(SiObject.style.left.split("px")[0])+200)/screen.width)-0.5)*30;
var Top = (((parseInt(SiObject.style.top.split("px")[0])+200)/screen.height)-0.5)*30;
document.getElementById("SpaceInvaderShadow").style.left = Left*(-1)+"px";
document.getElementById("SpaceInvaderShadow").style.top = Top*(-1)+"px";
}
function DynamicObject(TheID)
{
var self = this;
var id;
var opacify;
var transparent;
var object = document.getElementById(self.id);
self.blurAppearance = function (time)
{
var object = self.object;
var coef = 1/(time*24);
if(object.style.opacity <= 1)
{
object.style.opacity = self.opacify;
self.opacify+=coef;
setTimeout(function(){self.blurAppearance(time);},1000/24);
}
else
{
self.opacify = 0;
}
}
self.blurDisappearance = function (time)
{
var object = self.object;
var coef2 = 1/(time*24);
if(object.style.opacity > 0)
{
object.style.opacity = self.transparent;
self.transparent-=coef2;
setTimeout(function(){self.blurDisappearance(time);},1000/24);
}
else
{
self.transparent = 1;
}
}
self.DisplaceOnVector = function (x,y, oneShot)
{
var object = self.object;
var RealX = object.style.left.split("px")[0];
var RealY = object.style.top.split("px")[0];
object.style.left = parseInt(RealX)+x+"px";
object.style.top = parseInt(RealY)+y+"px";
if(!oneShot)
{
setTimeout(function(){self.DisplaceOnVector(x,y);},1000/24);
}
}
self.transparent = 1;
self.id=TheID;
self.opacify = 0.0;
self.object = document.getElementById(self.id);
}
Bon vous l'aurez vu, mon but n'était pas de faire un truc super optimisé, donc je serai plutôt dans la catégorie code complexe et parfois inutil (comme la POO totalement injustifiée :p)
Voici un dérivé des nombreux exemples "JS + Canvas", où j'ai remplacé Canvas, non pas par du HTML, mais par du SVG. Avec HTML5, il est désormais possible d'intégrer facilement du code SVG via une balise... <svg> . Et CSS permet de styler. En réalité, ce trouve ça plus pratique que canvas, car les différentes formes agissent comme des éléments HTML (on peur leur attacher des évènements, des effets de survol et tout).
@nino0105 : je pense que tu gagnes le prix du "code HTML le plus mal utilisé "
Les balises section ne devraient pas être utilisées pour ça. De même que leur attribut name. Et puis, avec CSS tu peux appliquer un inline-block sans le faire pour chaque balise .
Bonsoir je viens vous proposer ma version , elle fait 1,23 ko en version minimisé, j'ai utilisé l'HTML et surtout du JAVASCRIPT, toutes les divs sont générées par le JS , l'HTML est la juste pour le squelette de base: html head body. Je n'ai rien apporté de plus dans l'animation, j'ai cherché à faire au plus simple ce code ressemble sans doute au code de certains, honnêtement je n'ai pas encore regardé les exploits de tout le monde. bref vous le trouverez ici : http://quentinondet.fr/invaders/.
Le code plus lisible ici:
<html>
<head></head>
<body>
<script type="text/javascript">
var p1=new Array(3,5,9,10,11,12,13,16,18,20,23,25,27,29,30,31,32,33,34,35,36,38,40,42);
var rgb = new Array;
var invader;
function a()
{
setTimeout("document.body.removeChild(invader)",2700);
invader=document.createElement('div');
document.body.appendChild(invader);
invader.style.height='314px';
invader.style.width='366px';
invader.style.position='absolute';
invader.style.top=Math.round(Math.random()*(screen.height-314))+'px';
invader.style.left=Math.round(Math.random()*(screen.width-366))+'px';
for(k=0;k<3;k++)
{
rgb[k]=Math.round(Math.random()*255);
}
var y1=Math.round(Math.random());
var y2=Math.round(Math.random());
for(i=1;i<43;i++)
{
var element=document.createElement('div');
invader.appendChild(element);
element.style.margin='1px';
element.style.height='50px';
element.style.width='50px';
element.style.display='inline-block';
for(j=0;typeof(p1[j])!='undefined';j++)
{
if (i==p1[j])
{
element.style.background='rgb('+ rgb[0] +','+ rgb[1] +','+rgb[2] +')';
};
if (y1==1)
{
if (i==17)
{
element.style.background='black';
};
}
else
{
if (i==24)
{
element.style.background='black';
};
}
if (y2==1)
{
if (i==19)
{
element.style.background='black';
};
}
else
{
if (i==26)
{
element.style.background='black';
};
}
}
}
}
setInterval("a()",3000);
</script>
</body>
</html>
@quentin ondet Tu la peut être remarquer mais ton code ne fonctionne pas sur firefox (en tous cas le miens, version 21.0) par contre aucun problème avec chrome
(Sa m'affiche toute les case sur la même ligne verticale)
@sadiquo Merci de ta remarque, firefox n'a pas aimé mon float j'ai mis un display inline-block a la place ^^, j'en ai profité pour mettre a jour mon post. je n'ai pas vraiment pris le temps de le tester sur d'autres navigateurs. Par contre il peut y avoir un bug de timing entre la création et la suppression de div en cas de lag du navigateur et tu verrais plusieurs invaders ^^
Voila alors moi j'ai voulu faire le code le plus court possible en Javascript. Voici le Space Invaders de 618 caracteres (je sais qu'on peut faire beaucoup mieux mais j'ai pas reussi a faire moins):
J'ai amélioré ou plutôt changé l'algorithme d'affichage du monstre (ancienne version). Le monstre étant petit, ce n'est pas le meilleur algorithme mais le principale n'est-il pas de s'amuser ? :-)
Et la version texte :
space invaders :
// Notre bloc que nous allons cloner :
bloc :: rectangle, largeur vaut 10, hauteur vaut 10, plein vaut "oui"
// Variable pour le traitement
p :: nombre
// Position du monstre
x :: nombre
y :: nombre
début
tant que vrai, lis
x vaut hasard(500)
y vaut hasard(500)
couleur@bloc = couleurs{x/2}
// Ce tableau contient la position relative du bloc à x et y et le nombre de blocs à afficher à la suite :
pour chaque {{2,1},{4,1},{8,5},{15,1},{17,1},{19,1},{22,1},{24,1},{26,1},{28,8},{37,1},{39,1},{41,1}},lis
p vaut joker{0}
pour chaque joker{1},lis
x@bloc vaut x + p mod 7*11
y@bloc vaut y + entier(p/7)*11
projette clone(bloc)
incrémente p
ferme
ferme
couleur@bloc = "noir"
// Oeil 1
x@bloc vaut x + 2 * 11
y@bloc vaut y + (2 + x mod 2) * 11
projette clone(bloc)
// Oeil 2
x@bloc vaut x + 4 * 11
y@bloc vaut y + (2 + y mod 2) * 11
projette clone(bloc)
attends 1 seconde
efface toile
ferme
Petite version en Xlib, pour avoir un fond d'écran animé sous Linux. J'avais déjà regardé un peu X11, sans jamais vraiment essayer... Bah on peut pas vraiment dire que j'ai été très loin, mais bon, ça marche x).
j'ai deux écrans de tailles différentes, et parfois, le space invader va hors de la limite de celui de gauche... limite capturée par la vidéo, mais forcément pas visible à l'œil nu \ o /
j'ai pas géré le fait que les fenêtres puissent être déplacés, ça se voit à un moment de la vidéo.
Voilà, j'ai pas fait spécialement d'efforts pour avoir un code beau ou propre ou what ever, mais ça fonctionne plus ou moins :3.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Ma vraie biographie - Ex-Manager de la Validation sur le Site du Zéro - sdlm.be - Horus.aero
* Un wrapper C++ pour sqlite * Une alternative a boost units
* Un wrapper C++ pour sqlite * Une alternative a boost units
* Un wrapper C++ pour sqlite * Une alternative a boost units
Ma vraie biographie - Ex-Manager de la Validation sur le Site du Zéro - sdlm.be - Horus.aero
Retrouvez moi sur mon blog et ma chaine Youtube !