psyburn

Having issue with entity behaviour, after reproducing only the child reproduces agian.

Recommended Posts

Hello all,

I have been working on a little simulator having defeated a few issues i am now at a point where i am guessing where the issue is.
Probably it's something i missed somewhere else but i am not able to get it resolved, any help would be great :)

I am trying to have a plant reproduce itself realy basic and it kinda works. But after it has reproduced the plant should be able to do it a few more times before it is out of seeds. 
At this point the plant reproduces once and it's child also reproduce once and so on. But i want the parent plant to reproduce another x times. 

So for basic code this is what happens: 

GAME.JS
In the game.JS in the loaded function i place my plant in the pool

me.pool.register("basicPlant", game.BasicPlant);

PLAY.JS
I intialize my plantmanager which holds some logic for all the plants in the onResetEvent

this.plantManager = new game.PlantManager();


Then for the whole shabang this is the plantmanager. In the initializer the first plant is generated with the seed function.

game.PlantManager = me.Container.extend({
    init: function () {
        plantMap = this.CreatePlantMap(me.game.world.height)
        this.seed()
        return true
    },

    CreatePlantMap: function(rows) {
        var arr = [];
        for (var i=0;i<rows;i++) {
           arr[i] = this.CreatePlantTiles(i,rows);
        }
        return arr;
    },

    CreatePlantTiles: function(x,size) {
        var arr = [];
        for(var i=0;i<size;i++){
            arr.push({x:x, y:i, plant:false})   
        }
        return arr
    },

    collectTiles: function(x,y) {
        return [
            plantMap[x+1][y],
            plantMap[x+1][y+1],
            plantMap[x+1][y-1],
            plantMap[x][y+1],
            plantMap[x][y-1],
            plantMap[x-1][y],
            plantMap[x-1][y+1],
            plantMap[x-1][y-1]
        ]
    },

    getGrowthLocation: function(array) {
        plantlocation = array.map(function(a){if(!a.plant){return a}})
        clean = plantlocation.filter(function(a){ return a != undefined })
        random = clean[Math.floor(Math.random() * clean.length)]
        return random
    },

    createPlant: function (parrent) {
        x = parrent.pos.x 
        y = parrent.pos.y
        growthLocation = this.getGrowthLocation(this.collectTiles(x,y))
        if(growthLocation && !plantMap[x][y].plant){
            game.data.totalPlants++
            plantMap[x][y].plant = true
            plant = me.pool.pull("basicPlant", growthLocation.x, growthLocation.y);
            me.game.world.addChild(plant, 1);
        };
        return true
    },

    removePlant: function (plant) {
        game.data.totalPlants--
        me.game.world.removeChildNow(plant);
        plantMap[plant.pos.x][plant.pos.y].plant = false
        return true
    },

    seed: function(){
        this.createPlant({pos:{x:50,y:50}})
        return true
    },

});


And finaly the plant itself
 

game.BasicPlant = me.Entity.extend({

    init:function (x, y) {
        this._super(me.Entity, "init", [x, y, {
            image: "green",
            width: 1,
            height: 1,
        }]);
        this.id = [x,y]
        this.energy = 100
        this.seeds = 5
        this.max_age = 1500
        this.age = 0
        return true
    },

    update: function (dt) {
        this._super(me.Entity, "update", [dt]);
        this.energy++
        this.age++
        if(this.energy == 0 || this.age == this.max_age){
            this.die()
        }
        if(this.energy > 150 && this.seeds > 0){
            this.multiply()
            this.seeds = this.seeds - 1
        }
        return true;
    },

    multiply : function(){
        this.energy -= 100
        game.playScreen.plantManager.createPlant(this) 
        return true
    },

    die : function(){
        game.playScreen.plantManager.removePlant(this);
        return true
    }
});

 

Share this post


Link to post
Share on other sites

First thing I noticed is that you are using a bunch of global variables in the PlantManager class, probably unintentionally. plantMap should probably be a class property: this.plantMap. The others (plantLocation, clean, random, x, y, growthLocation, plant) should be declared with var (or let if you're using ES6 syntax). Fixing the variable scoping may not solve the issue, though.

The second thing I noticed is that on the edges of the tilemap, the plantManger.getGrowthLocation() method will raise an exception, because you're filtering the undefined values after attempting to access the plant property on undefined. You can easily solve this by filtering the array before mapping the values.

Ah, here is the problem, on this line:

if(growthLocation && !plantMap[x][y].plant){

The boolean is pointing at the parent location, which is initially false. You want to check the value of growthLocation.plant here, and assign true to this property inside the condition body. Also, as a side note, you should set plantMap[50][50].plant = true in the seed method, otherwise it will grow a second plant in that location.

Also, one question and an observation: Are all of these plants supposed to be 1x1 pixel each? Seems like you're going to end up creating a ton of plant objects if that's true! A modern retina display has over 5 million pixels, as an example. So a full screen plant-reproduction-simulator on such a device will create a maximum of 5,184,000 plant objects. The game will become unplayably slow before it fills the entire screen with green pixels, though.

Share this post


Link to post
Share on other sites

Hey Parasyte, 

The if statement was indeed the issue, thanks for looking through the code :). Also thanks for all the other tips and heads up i really appreciate it.

The playing field is for now a maximum of 100px by 100px so that will reduce the total amount of plants to 10k. Now this is working as intended my goal is to build a simple "creature" which feeds of the grass (removing energy and adding it to itself)and moves around/multiplies as needed. 

For v1 the goal is that the attributes of the creature and the plants have a chance to be randomly a little bit bigger or smaller than it's parent, in other words trying to simulate evolution. 

Let me say again, Thanks for your time and help :)

Share this post


Link to post
Share on other sites

Glad it all worked out!

10,000 is also quite a lot; each of those entities needs to update in a tight loop on every frame, and again in a second tight loop to draw. It's a very similar problem that the particle emitter experiences; but we have the luxury that the particles are much lighter-weight than entities. A more efficient implementation would be moving the BasicPlant logic into the PlantManager. The manager is already recording the state of each plant in a 2D array, so it's not a huge leap to have the PlantManager draw each plant to an off-screen canvas when a new plant is spawned. That will reduce the update and draw calls from O(n) to O(1) runtime, which is huge! (Where n is the maximum number of plants.) And updating the plant state from the manager will be much lighter weight than the Entity class, too. So that's also a win.

It sounds like a really cool concept, though. I've always wanted to make a game with some evolution simulation elements.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.