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

Revision 974, 18.0 KB checked in by dave, 10 years ago (diff)

sped up

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