Skip navigation.
Home
That which cannot be rendered in binary is by definition a delusion
 

Being John Bunny

The Being code is the master framework for a Rabbit (and hopefully other animals ... wolves, mice, perhaps even people?). The front of the class has to do with basic abilities (most of which have no usage in the current code): 

/*
    * Being.fx
     *
     * Created on Mar 22, 2009, 11:44:20 AM
     */

package gaeus.beings;

import javafx.scene.*;
import java.lang.Math;
import javafx.animation.*;

/**
* @author daveedelhart
*/

public def GENDER_MALE = 0;
public def GENDER_FEMALE = 1;

public abstract class Being extends CustomNode {

    function Being() {
        println("create being()");
        random_gender();
        start_heart();
    }

    protected function random_gender(){
        if (Math.random() > 0.5)
        {
            gender = GENDER_MALE;
        }
        else {
            gender = GENDER_FEMALE;
            add_action(
                FindMate{
                    being: this
                }
            );
        }
    }

    /************************ ATTRIBUTES ****************************/

    //NOTE: these stats represent SPECIES norm -- 100.0 == 100% of normal.
    public var rel_mind: Float = 100.0;
    public var rel_body: Float = 100.0;
    public var rel_speed: Float = 100.0;
    public var rel_spirit: Float = 100.0;

    protected def mind_scale: Float = 1.0;
    protected def body_scale: Float = 1.0;
    protected def speed_scale: Float = 1.0;
    protected def spirit_scale: Float = 1.0;

/********************* STATS ********************/

 

public function mind(): Float { return rel_mind * mind_scale; } public function body(): Float { return rel_body * body_scale; } public function speed(): Float { return rel_speed * speed_scale; } public function spirit(): Float { return rel_spirit * spirit_scale; } /****************** ENERGY AND HEALTH *************************/ /* energy represents "carbs to burn". you can(and animals will) stuff yourself past 100, but it won't help your speed being fat. You have to have a high energy store to get horny. Health represents your wounds, illness, etc. Health below 33 represents mortal wounds -- without care you will bleed to death. */ public var energy = 100.0; public var health = 100.0; public function use_energy(e: Float) { energy = Math.max(0, energy - e); } public function hungry() : Boolean { if (energy < 50.0) { return true; } else { return false; } } public var size: Float = 100.0; public var lifespan_years = 50; // the AVERAGE expected lifespan. public var age = 0.0; public var gender = -1; def MUTATION = 5.0; // the percent variation that species will vary from their parents.

The heartbeat of the animal drives the update routine of the current action; every heartbeat the being reevaluates its environment.

     /****************** HEARTBEAT ********************/

    var heartbeat: Timeline;

    function heart_beat() {
        var cost = 0.0;
        println("HeartBeat");
        if (action != null)
        {
            action.update();
        }
        energy -= cost;
    }

    protected function start_heart() : Void {
        heartbeat = Timeline {
            repeatCount: Timeline.INDEFINITE
            keyFrames: [
                KeyFrame {
                    time: 1s
                    canSkip: false
                    action: {
                        function() {
                            this.heart_beat();
                        }
                    }
                }
            ]
        }

    }

 

 This section covers action loading. Each potential action is stored in the action stack through the add_action() method, and retrieved by name. the current action is stored in the action field. The actions themselves should govern their own lifespan and choose the successive action; i.e., when the chasemate action ends then either the breed action begins (if a mate is caught) or a default action (graze?) is kicked off. Currently only one action can be active at any given moment.

/* @@@@@@@@@@@@@@@@@@@@@@@@@@@ ACTIVITY @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */

    public var activity = 0;

    var action_stack : Action[];

    var action : Action;

    public function add_action(a: Action)
    {

       action_stack = for (old_a in action_stack where (a.name.equalsIgnoreCase(a.name)) == false) old_a;

       insert a into action_stack;
       true;
    }

    public function start_action(name: String){
        println("trying to start {name}");
        if (action != null)
        {
            if (action.status == 2)
            {
                action.stop();
            }
        }

        action = null;
        for (a in action_stack)
        {
            if (a.name.equalsIgnoreCase(name))
            {
                action = a;
                a.start();
                println("found, starting {name}");
            }
        }
        action.name;
    }

Movement is a "meta action" currently -- refactoring it into a sub-action might be good later but for now this universal utility is in the Being class definition itself. It is based on the koi pond example in the JavaFX docs.

    /********************** WALK ***************************/

    var move: Timeline;
    public var dest_x = 0.0;
    public var dest_y = 0.0;

    public function run_to(b: Being) {
        run_to(b.translateX, b.translateY);
    }

    public function run_to(x: Number, y: Number) {
        go_to(x, y, speed());
    }

    public function walk() {

        def angle = Math.random() * 2 * Math.PI;

        def x = Math.sin(angle) * sight_range() / 2;
        def y = Math.cos(angle) * sight_range() / 2; // reversed? who cares.
        walk(x, y);
    }

    // move in a vector from present point, at walk speed.
    public function walk(x: Float, y: Float) {
        println("walking");
        walk_to(translateX + x, translateY + y);
    }

    public function walk_to(x: Number, y: Number) {
        var walk_speed = Math.sqrt(speed());
        this.go_to(x, y, walk_speed);
    }

    public function stop_moving() {
        move.stop();
    }

    public function go_to(x: Number, y: Number, speed) {
        stop_moving();

        var xoff = x - translateX;
        var yoff = y - translateY;
      
        dest_x = x;
        dest_y = y;

        var t = 1s * distance_to(x, y) / speed; //speed = 100px / sec
        move = Timeline {
            keyFrames: [
                KeyFrame {
                    time: t
                    values: [
                        translateX => dest_x tween Interpolator.EASEOUT,
                        translateY => dest_y tween Interpolator.EASEOUT,
                    ]
                    action: {
                        function(){
                          
                            if (action.update() > 1)
                            {
                                stop_moving();
                            }
                        }

                    }

                }
            ]
        }
        move.play();
    }

    /********************* BREEDING ****************/

Here is some utility code for genetic reproduction.

 

       
         //  public abstract function breed_with(mate: Being);

    public function mutate_from_parents(Dad: Being, Mom: Being) :
    Void {
        rel_mind = mutate_attribute(Dad.rel_mind, Mom.rel_mind);
        rel_body = mutate_attribute(Dad.rel_body, Mom.rel_body);
        rel_spirit = mutate_attribute(Dad.rel_spirit, Mom.rel_spirit);
        rel_speed = mutate_attribute(Dad.rel_speed, Mom.rel_speed);
    }

    protected function mutate_attribute(a1: Float, a2: Float) : Float {
        return (a1 + a2) / 2.0 + (MUTATION * Math.random()) - (MUTATION * Math.random());
    }

Being senses are generic -- at this point it is simply a funtction of distance and intelligence.

/********************** DETECTION ********************/

    // determines if a target is in the range of sight.

    public function can_see(target: Being) : Boolean {
        if (distance_to(target) > sight_range()) {
            return false;
        } else {
            return true;
        }
    }

    /************************ POPULATION *************************/
abstract function fellow_beings() : Being[];
    public function sight_range(): Float {
    return 200 * mind();
}
public function distance_to(target: Being) {
    var dx = translateX - target.translateX;
    var dy = translateY - target.translateY;
    return Math.sqrt((dx * dx) + (dy * dy));
}
public function distance_to(x: Number, y: Number) {
    var dx = translateX - x;
    var dy = translateY - y;
    return Math.sqrt((dx * dx) + (dy * dy));
}
public function detect_beings(): Being[] {
    return [];
}
public function detect_fellow_beings(): Being[] {
    var found_beings: Being[] = [];
    for (b in fellow_beings()) {
        if (can_see(b))
        {
            insert b into found_beings;
        }
    }
    found_beings;
   }
}

What this gives us is a base class for an entity that can

  1. Has ability statistics and an energy and health pool
  2. Move to a point
  3. Move to another being
  4. Accept an action to enable other types of activity
  5. Detect other beings of all types, or all beings of the same species, within its range of sight

Not bad so far...

Post new comment

  • Allowed HTML tags: <a> <p> <span><small> <div> <h1> <h2> <h3> <h4> <h5> <h6> <img> <map> <area> <hr> <br> <br /> <ul> <ol> <li> <dl> <dt> <dd> <table> <tr> <td> <em> <b> <u> <i> <strong> <font> <del> <ins> <sub> <sup> <quote> <blockquote> <pre> <address> <code> <cite> <embed> <object> <param> <strike> <caption>
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.

More information about formatting options