source: scenarios/GerminationX/fungi/src/Fungi.hx @ 987

Revision 987, 18.2 KB checked in by dave, 9 years ago (diff)

new plants and butterflies

Line 
1// GerminationX Copyright (C) 2010 FoAM vzw    \_\ __     /\
2//                                          /\    /_/    / / 
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU Affero General Public License as
5// published by the Free Software Foundation, either version 3 of the
6// License, or (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU Affero General Public License for more details.
12//
13// You should have received a copy of the GNU Affero General Public License
14// along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16import haxe.Log;
17
18import truffle.Truffle;
19import truffle.interfaces.Key;
20
21import truffle.Vec3;
22import truffle.Vec2;
23import truffle.RndGen;
24import truffle.Circle;
25import truffle.Entity;
26import truffle.SpriteEntity;
27import truffle.SkeletonEntity;
28import truffle.Bone;
29
30import Critters;
31
32// todo: remove this
33import flash.display.Graphics;
34import flash.display.Shape;
35
36 
37//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38
39class Cube extends SpriteEntity
40{       
41        public function new(world:World, pos:Vec3)
42        {
43                super(world, pos, Resources.Get("blue-cube"));
44        }
45       
46        public function UpdateTex(rnd:RndGen)
47        {
48                if (LogicalPos.z%2==0)
49        {
50            Spr.ChangeBitmap(Resources.Get(
51                rnd.Choose(["rock-cube-01","rock-cube-02","rock-cube-03"])));
52                }
53                else
54                {
55            Spr.ChangeBitmap(Resources.Get(
56                rnd.Choose(["rock-cube-04","rock-cube-05","rock-cube-06"])));
57        }
58        }
59}
60
61//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
62
63class Plant extends SpriteEntity
64{
65        public var Owner:String;
66        var PlantScale:Float;
67        public var Age:Int;
68    var Scale:Float;
69    var PlantType:String;
70    var State:String;
71    var Seeds:Array<Sprite>;
72    var Layer:String;
73
74        public function new(world:World, owner:String, pos, type:String, state:String)
75        {
76                super(world,pos,Resources.Get(type+"-"+state),false);
77        PlantType=type;
78        State=state;
79                Owner=owner;
80        PlantScale=0;
81        //NeedsUpdate=true;
82        Seeds=[];
83
84        Layer="none";
85        if (type=="plant-001") Layer="cover";
86        if (type=="plant-002") Layer="canopy";
87        if (type=="plant-003") Layer="vertical";
88
89        Spr.Hide(false);
90       
91        var tf = new flash.text.TextField();
92        tf.text = "This plant belongs to the "+type+" species, part of the "+
93            Layer+" layer. "+Owner+" planted this.";
94        tf.x=Spr.Pos.x-50;
95        tf.y=Spr.Pos.y-30-Spr.Height*Spr.MyScale.y;
96        tf.height=40;
97        tf.background = true;
98        //tf.backgroundColor = 0x8dd788;
99        tf.border = true;
100        tf.wordWrap = true;
101        tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
102        var t = new flash.text.TextFormat();
103        t.font = "Verdana";
104        t.size = 8;               
105        t.color= 0x000000;           
106        tf.setTextFormat(t);
107        Spr.parent.addChild(tf);
108        tf.visible=false;
109        Spr.MouseOver(this,function(c) { tf.visible=true; });
110        Spr.MouseOut(this,function(c) { tf.visible=false; });
111        }
112
113    public function StateUpdate(state,world:World)
114    {
115        State=state;
116        if (State!="decayed")
117        {
118            Spr.ChangeBitmap(Resources.Get(PlantType+"-"+State));
119        }
120        if (State=="fruit-c" && Seeds.length==0)
121        {
122            Fruit(world);
123        }
124    }
125
126    override function Destroy(world:World)
127    {
128        super.Destroy(world);
129        for (seed in Seeds)
130        {
131            world.RemoveSprite(seed);
132        }
133    }
134       
135        public override function Update(frame:Int, world:World)
136        {
137                super.Update(frame,world);
138        }
139
140    public function Fruit(world:World)
141    {
142        var f=new Sprite(Spr.Pos.Add(new Vec2(0,-Spr.Height/2)),
143                         Resources.Get("seed"));
144        world.AddSprite(f);
145        Seeds.push(f);
146        f.MouseDown(this,function(p)
147        {           
148            if (world.MyName!="")
149            {
150                var s=new Seed(p.PlantType);
151                if (world.Seeds.Add(world,s))
152                {
153                    p.Seeds.remove(f);
154                    world.RemoveSprite(f);
155                }
156            }
157        });
158    }
159}
160
161//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
162
163class Spirit extends SkeletonEntity
164{
165    public var Name:String;
166
167    var Debug:flash.text.TextField;
168        var BG:Graphics;
169    var RawEmotions:Dynamic;
170    var Emotions:Dynamic;
171    var DesiredPos:Vec2;
172   
173        public function new(world:World, name:String, pos)
174        {
175                super(world,pos);
176        Name = name;
177        Speed=0.1;
178        UpdateFreq=5;
179        Hide(true);
180        DesiredPos=new Vec2(LogicalPos.x,LogicalPos.y);
181        RawEmotions={Love:0,Hate:0,Hope:0,Fear:0,Satisfaction:0,
182                     Relief:0,/*Fears_Confirmed:0,*/Disappointment:0,
183                     Joy:0,Distress:0,/*Happy_For:0,*/Pitty:0,
184                     Resentment:0,Gloating:0,Pride:0,Shame:0,
185                     Gratification:0,Remorse:0,Admiration:0,
186                     Reproach:0,Gratitude:0,Anger:0};
187        Emotions={Love:0,Hate:0,Hope:0,Fear:0,Satisfaction:0,
188                  Relief:0,/*Fears_Confirmed:0,*/Disappointment:0,
189                  Joy:0,Distress:0,/*Happy_For:0,*/Pitty:0,
190                  Resentment:0,Gloating:0,Pride:0,Shame:0,
191                  Gratification:0,Remorse:0,Admiration:0,
192                  Reproach:0,Gratitude:0,Anger:0};
193    }
194
195        public function BuildDebug(c)
196    {
197        var tf = new flash.text.TextField();
198        tf.text = "nowt yet.";
199        tf.x=Pos.x-150;
200        tf.y=Pos.y-25;
201        tf.height=150;
202        tf.width=140;
203        tf.background = false;
204        tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
205        //tf.backgroundColor = 0x8dd788;
206        tf.border = true;
207        tf.wordWrap = true;
208        var t = new flash.text.TextFormat();
209        t.font = "Verdana";
210        t.size = 8;               
211        t.color= 0x000000;           
212        tf.setTextFormat(t);
213
214        var figures:Shape = new Shape();
215        BG = figures.graphics;
216        BG.beginFill(0xffffff,0.5);
217        BG.drawRect(tf.x,tf.y,tf.width,tf.height);
218        BG.endFill();
219        figures.visible=false;
220        cast(c,truffle.flash.FlashWorld).addChild(figures);
221
222        c.addChild(tf);
223        Debug=tf;
224        tf.visible=false;
225
226        Root.MouseDown(c,function(c)
227        {
228            tf.visible=!tf.visible;
229            figures.visible=!figures.visible;
230        });
231        }
232
233    public function UpdateEmotions(e:Dynamic,world:World)
234    {
235        SetTilePos(new Vec2(Std.parseInt(e.tile.x),
236                            Std.parseInt(e.tile.y)));
237
238       
239        var dst = new Vec2(Std.parseInt(e.emotionalloc.x),
240                              Std.parseInt(e.emotionalloc.y));
241
242        if (dst.x!=DesiredPos.x || dst.y!=DesiredPos.y)
243        {
244            DesiredPos = dst;
245            while (world.Get("Spirit",dst)!=null)
246            {
247                dst = dst.Add(new Vec2(world.MyRndGen.Choose([-2,0,2]),
248                                       world.MyRndGen.Choose([-2,0,2])));
249            }
250            LogicalPos = new Vec3(dst.x,dst.y,4);
251        }
252
253        RawEmotions = e.emotions;
254
255        var ee = e.fatemotions.content;
256        var mood=Std.parseFloat(ee[0].content[0]);
257
258        var text=Name+"\nMood:"+ee[0].content[0]+"\n";
259        text+="Emotions:\n";
260        for (i in 1...ee.length)
261        {
262            text+=ee[i].attrs.type+" "+ee[i].attrs.direction+"\n";
263            //text+=ee[i].attrs.cause+"\n";
264        }
265
266        text+="Actions:\n";
267        var acs = cast(e.fatactions,Array<Dynamic>);
268        for (i in 0...acs.length)
269        {
270            text+=acs[i].msg+"\n";
271        }
272
273        Debug.text=text;
274
275        var t = new flash.text.TextFormat();
276        t.font = "Verdana";
277        t.size = 8;               
278        t.color= 0x000000;           
279        Debug.setTextFormat(t);
280        Debug.x=Pos.x-150;
281        Debug.y=Pos.y-25;
282
283        BG.clear();
284        BG.beginFill(0xffffff,0.5);
285        BG.drawRect(Debug.x,Debug.y,Debug.width,Debug.height);
286        BG.endFill();
287
288        //trace(text);
289    }
290
291    override function Update(frame:Int, world:World)
292    {
293        for (f in Reflect.fields(Emotions))
294        {
295            // do a linear blend to smooth out changes in emotions
296            Reflect.setField(Emotions,f,
297            Reflect.field(Emotions,f)*0.95+Reflect.field(RawEmotions,f)*0.05);
298            //trace(f);
299        }
300
301        //Draw(cast(world,truffle.World));
302        var c=this;
303        Root.Recurse(function(b:Bone,depth:Int)
304        {
305            var excitement = c.Emotions.Love+c.Emotions.Admiration;
306            if (excitement>10) excitement=10;
307           
308            b.SetRotate(excitement*5*Math.sin(
309                             (((10-depth)+frame*0.04+c.Emotions.Gratitude*0.01)+
310                             c.Emotions.Joy*0.1)) +
311            ((world.MyRndGen.RndFlt()-0.5)*10*(c.Emotions.Hate+
312                    c.Emotions.Distress)));
313           
314        });
315
316        super.Update(frame,world);
317    }
318}
319
320//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
321
322class Seed
323{
324    public var Type:String;
325    public var Spr:Sprite;
326
327    public function new(t:String)
328    {
329        Type=t;
330        Spr=new Sprite(new Vec2(0,0),Resources.Get("seed"));
331    }
332}
333
334class SeedStore
335{
336    var Seeds:Array<Seed>;
337    var Size:Int;
338
339    public function new(size:Int)
340    {
341        Seeds = [];
342        Size = size;
343    }
344
345    public function Add(world:World,s:Seed) : Bool
346    {
347        if (Seeds.length<Size)
348        {
349            Seeds.push(s);
350            s.Spr.SetPos(new Vec2(20+Seeds.length*10,30));
351            //cast(world,truffle.flash.FlashWorld).addSprite(s.Spr);
352            //trace("did it...");
353            s.Spr.Update(0,null);
354            return true;
355        }
356        return false;
357    }
358
359    public function Remove(world:World) : String
360    {
361        if (Seeds.length>0)
362        {
363            var s = Seeds.pop();
364//            world.RemoveSprite(s.Spr);
365            return s.Type;
366        }
367        else
368        {
369            return "";
370        }
371    }
372}
373
374//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
375
376class FungiWorld extends World
377{
378        public var Width:Int;
379        public var Height:Int;
380        var Objs:Array<Cube>;
381        public var WorldPos:Vec3;
382        var MyRndGen:RndGen;
383        public var MyTextEntry:TextEntry;
384        public var Plants:Array<Plant>;
385    public var TheCritters:Critters;
386        var MyName:String;
387    var Frame:Int;
388    var TickTime:Int;
389    var PerceiveTime:Int;
390    var Spirits:Array<Spirit>;
391    public var Seeds:SeedStore;
392    var Server : ServerConnection;
393
394        public function new(w:Int, h:Int)
395        {
396                super();
397                Frame=0;
398        TickTime=0;
399        PerceiveTime=0;
400                Width=w;
401                Height=h;
402                Plants = [];
403        Objs = [];
404        Spirits = [];
405        Seeds = new SeedStore(1);
406                WorldPos = new Vec3(0,0,0);
407                MyRndGen = new RndGen();
408        Server = new ServerConnection();
409        MyName = "";
410
411
412        var arrow1 = new SpriteEntity(this,new Vec3(7,-2,1), Resources.Get("arr3"));
413        arrow1.Spr.MouseUp(this,function(c) { c.UpdateWorld(c.WorldPos.Add(new Vec3(0,-1,0))); });
414        arrow1.Spr.MouseOver(this,function(c) { arrow1.Spr.SetScale(new Vec2(1.1,1.1)); arrow1.Spr.Update(0,null); });
415        arrow1.Spr.MouseOut(this,function(c) { arrow1.Spr.SetScale(new Vec2(1,1)); arrow1.Spr.Update(0,null); });
416 
417        var arrow2=new SpriteEntity(this,new Vec3(10,21,1), Resources.Get("arr4"));
418        arrow2.Spr.MouseUp(this,function(c) { c.UpdateWorld(c.WorldPos.Add(new Vec3(0,1,0))); });
419        arrow2.Spr.MouseOver(this,function(c) { arrow2.Spr.SetScale(new Vec2(1.1,1.1)); arrow2.Spr.Update(0,null); });
420        arrow2.Spr.MouseOut(this,function(c) { arrow2.Spr.SetScale(new Vec2(1,1)); arrow2.Spr.Update(0,null); });
421 
422        var arrow3=new SpriteEntity(this,new Vec3(-2,7,1), Resources.Get("arr2"));
423        arrow3.Spr.MouseUp(this,function(c) { c.UpdateWorld(c.WorldPos.Add(new Vec3(-1,0,0))); });
424        arrow3.Spr.MouseOver(this,function(c) { arrow3.Spr.SetScale(new Vec2(1.1,1.1)); arrow3.Spr.Update(0,null); });
425        arrow3.Spr.MouseOut(this,function(c) { arrow3.Spr.SetScale(new Vec2(1,1)); arrow3.Spr.Update(0,null); });
426
427        var arrow4=new SpriteEntity(this,new Vec3(20,10,1), Resources.Get("arr1"));
428        arrow4.Spr.MouseUp(this,function(c) { c.UpdateWorld(c.WorldPos.Add(new Vec3(1,0,0))); });
429        arrow4.Spr.MouseOver(this,function(c) { arrow4.Spr.SetScale(new Vec2(1.1,1.1)); arrow4.Spr.Update(0,null); });
430        arrow4.Spr.MouseOut(this,function(c) { arrow4.Spr.SetScale(new Vec2(1,1)); arrow4.Spr.Update(0,null); });
431
432                for (y in 0...h)
433                {
434                        for (x in 0...w)
435                        {
436                                var ob:Cube = new Cube(this,new Vec3(0,0,0));
437             
438                ob.Spr.MouseDown(this,function(c)
439                {
440                    var type=c.Seeds.Remove(cast(c,truffle.World));
441                    if (type!="")
442                    {
443                        c.AddServerPlant(ob.LogicalPos.Add(new Vec3(0,0,1)),type);
444                    }
445                });
446                                Objs.push(ob);
447                        }
448                }
449
450                UpdateWorld(new Vec3(0,0,0));
451               
452                MyTextEntry=new TextEntry(300,10,310,30,NameCallback);
453                addChild(MyTextEntry); 
454
455        TheCritters = new Critters(this,3);
456
457        Update(0);
458        SortScene();
459        var names = ["CanopySpirit","VerticalSpirit","CoverSpirit"];
460        var positions = [new Vec3(0,5,4), new Vec3(7,0,4), new Vec3(2,10,4)];
461
462        for (i in 0...3)
463        {
464            Server.Request("spirit-sprites/"+names[i],
465            this,
466            function (c,data:Array<Dynamic>)
467            {
468                var sp:Spirit = new Spirit(c,names[i],positions[i]);
469                sp.NeedsUpdate=true;
470                sp.Build(c,data);
471                sp.BuildDebug(c);
472                c.SortScene();
473                c.Spirits.push(sp);
474            });
475        }
476        }
477       
478        public function NameCallback(name)
479        {
480                removeChild(MyTextEntry);
481                MyName=name;
482                //WorldClient.GetPlants(cast(WorldPos.x,Int),cast(WorldPos.y,Int));
483        }
484       
485        public function UpdateWorld(pos:Vec3)
486        {
487                WorldPos=pos;
488        SetCurrentTilePos(new Vec2(pos.x,pos.y));
489               
490                var circles = [];
491        for (x in -1...2)
492                {
493                        for (y in -1...2)
494                        {
495                                MyRndGen.Seed(cast((WorldPos.x+x)+(WorldPos.y+y)*139,Int));
496                                for (i in 0...5)
497                                {
498                                        var pos = new Vec3(MyRndGen.RndFlt()*15+x*15,
499                                       MyRndGen.RndFlt()*15+y*15,
500                                                                           0);           
501                                        circles.push(new Circle(pos, MyRndGen.RndFlt()*4));
502                                }
503                        }
504                }
505               
506               
507                for (i in 0...Objs.length)
508                {
509                        var pos=new Vec3(i%Width,Math.floor(i/Width),-1);
510                        MyRndGen.Seed(cast(WorldPos.x+pos.x+WorldPos.y+pos.y*139,Int));
511                        var inside:Bool=false;
512                        for (c in circles)
513                        {
514                                if (c.Inside(pos)) pos.z=0;
515                        }
516
517                        Objs[i].LogicalPos=pos;
518                        Objs[i].UpdateTex(MyRndGen);
519            Objs[i].Update(0,this);
520                }
521
522        ClearPlants();         
523        }
524
525        public function AddServerPlant(pos:Vec3,type)
526        {       
527        if (MyName!=null && SpaceClear(pos))
528        {
529            var size=MyRndGen.RndFlt()+0.5;
530            Server.Request("make-plant/"+Std.string(cast(WorldPos.x,Int))+"/"+
531                                         Std.string(cast(WorldPos.y,Int))+"/"+
532                                         Std.string(cast(pos.x,Int))+"/"+
533                                         Std.string(cast(pos.y,Int))+"/"+
534                                         type+"/"+
535                                         MyName+"/"+
536                                         Math.round(size*100),
537            this, function (c,data) {});       
538        }
539        }
540
541    public function ClearPlants() : Void
542    {
543        for (plant in Plants)
544        {
545            Remove(plant);
546        }
547        Plants = [];
548        }
549       
550        public function GetCube(pos:Vec3) : Cube
551        {
552                return Objs[cast(pos.x+pos.y*Width,Int)];
553        }
554               
555    public function SpaceClear(pos:Vec3)
556    {
557        for (plant in Plants)
558        {
559            if (plant.LogicalPos.Eq(pos)) return false;
560        }
561        return true;
562    }
563       
564        override public function Handle(e:Int)
565        {
566        super.Handle(e);
567        Update(0);
568        }
569
570    public function UpdateGhosts(c,t:Dynamic)
571    {
572        for(i in 0...t.length)
573        {
574            for (g in Spirits)
575            {
576                if (g.Name==t[i].name)
577                {
578                    g.UpdateEmotions(t[i],this);
579                }
580            }
581        }
582    }
583
584    override function Update(time:Int)
585    {
586        super.Update(time);
587
588        Server.Update();
589        TheCritters.Update();
590       
591        if (time>TickTime)
592        {
593            Server.Request("spirit-info",this,UpdateGhosts);
594
595            Server.Request("get-tile/"+Std.string(cast(WorldPos.x,Int))+"/"
596            +Std.string(cast(WorldPos.y,Int)),
597            this,
598            function (c:truffle.World,d)
599            {
600                var data:Array<Dynamic>=cast(d.entities,Array<Dynamic>);
601                for (p in data)
602                {
603                    var worldpos = new Vec2(p.pos.x,p.pos.y);
604                    var e = c.Get("Plant",worldpos);
605                    if (e==null)
606                    {
607                        //trace("making new plant");
608                        var cube = c.Get("Cube",worldpos);
609                        if (cube!=null)
610                        {
611                            var pos = new Vec3(p.pos.x,p.pos.y,cube.LogicalPos.z+1);   
612                            var plant = new Plant(c,p.owner,pos,p.type,p.state);
613                            c.Plants.push(plant);
614                        }
615                    }
616                    else
617                    {
618                        //trace("updating plant");
619                        //trace(e);
620                        //trace(p.state);
621                        cast(e,Plant).StateUpdate(p.state,c);
622                    }
623                }
624                c.SortScene();
625            });           
626           
627            TickTime=time+100;
628        }
629    }
630
631}
632
633//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
634
635class Fungi extends App
636{
637    public function new()
638        {
639//        Log.setColor(0xFFFFFF);
640        super(new FungiWorld(15,15));
641    }
642       
643    static function main()
644        {
645        var m:Fungi = new Fungi();
646    }
647}
Note: See TracBrowser for help on using the repository browser.