1

i am making a game in which i want to have a "player" object, and i want to do this in a function, but i also want to bind the object to the image displayed as the player. i want this because i later create monsters, and i want the hover to have a similar effect with a hover, but be based on that object's property's (i.e. display their health). my current method does not use .data(), and employ's backwards coding, while it works fine for what i have now, i cant expand my game with this code so i want to fix it up.

here is my attempt

function Player() {
    this.currentLocation = 0;
    printPlayer(this);
}

function printPlayer(p) {
    $("#" + p.currentLocation).html( "<img src = 'http://3.bp.blogspot.com/-kAhN0HX-MBk/T_5bApfhbJI/AAAAAAAAAuI/lUww8xT9yV8/s1600/smileys_001_01.png'" +
        "class='onTop displayCurrentHealth' alt='you' border='0' />" +
        "<div class = 'healthLost hide'></div>");
}
var player = new Player();
console.log($("#" + player.currentLocation).data("inFight", "false"));
console.log($("#" + player.currentLocation).data("inFight"));
console.log($("#" + player.currentLocation).data(!"inFight"));

this is my console.log() result

Object[]
adventure.js (line 62)
null
adventure.js (line 63)
null
adventure.js (line 64)

here is my old code

function Player(id) {
    this.id = id;
    this.healthid = this.id + "health";
    this.displayText = "<img src = 'http://3.bp.blogspot.com/-kAhN0HX-MBk/T_5bApfhbJI/AAAAAAAAAuI/lUww8xT9yV8/s1600/smileys_001_01.png'" +
        "class='onTop displayCurrentHealth' id='" + this.id + "' alt='you' border='0' />" +
        "<div id = '" + this.healthid + "' class = 'healthLost hide'></div>";
    this.inFight = false;
    this.currentLocation = 0;
    this.xp = 0;
    this.level = 1;
}

Object.defineProperty(player,"health",{ 
    set: function() { 
    return 100 + ( this.level * 150 );
    }, 
    get: function() { 
    return 100 + ( this.level * 150 );
    },
    enumerable: true  
} );

player.currentHealth = player.health;

Object.defineProperty(player,"strength",{ 
    set: function() { 
        return ( this.level * 5 );
    }, 
    get: function() { 
        return ( this.level * 5 );
    },
    enumerable: true 
} );

Object.defineProperty(player,"hitRating",{ 
    set: function() { 
        return 3 + ( this.level );
    }, 
    get: function() { 
        return 3 + ( this.level );
    },
    enumerable: true 
} );

how do i create that as jquery data(), dynamically in a function, onto a image that can have a changing location?

--update--

i added in this

$("#" + player.currentLocation).data("foo");
console.log($("#" + player.currentLocation).data());

which also returns null.

--update--

ok so i take it i need some sort of mvc, is there a way to do this in just javascript/jquery? and if yes how? please provide full explanation and/or links.

6
  • The key to keeping the data is to keep the DOM element that contains it. Don't draw a new player sprite every time - create one and move it around. This way all attached data and behavior stay where they belong. Commented Sep 3, 2013 at 9:50
  • @Tomalak i dont know how to do that but if you could tell me that would be awesome really Commented Sep 3, 2013 at 18:46
  • 1
    Instead of $("#" + p.currentLocation).html("<a new img>") do var $player = $("<img id='player' ...>").data("whatever", value) and $("#" + p.currentLocation).append($player). Don't delete the <img> that represents the player. Just move it around. (Hint: .append() moves a node in the DOM since a node can only ever be appended to one parent.) Commented Sep 3, 2013 at 18:53
  • @Tomalak tyvvm if you put that in a answer i will accept it Commented Sep 3, 2013 at 18:56
  • Note that my answer is quite a rough sketch, derived from your code. You definitely should look into HTML templating and probably MVC/MVVM, too. I'd recommend knockout.js for a combined, declarative model-binding/templating approach with a not-so-steep learning curve and yet quite a lot of power. (On the other hand, doing things without yet another framework first lets you learn more. Once you're confident with jQuery and have something working with it, move on and use a model/view framework like backbone or knockout. There are dedicated gaming frameworks, too.) Commented Sep 3, 2013 at 20:28

2 Answers 2

1

As pointed out in the comments, the key to keeping the data is keeping the DOM node it is attached to.

One way to start could look like this (going from your code, making the smallest possible change):

function Player() {
    var self = this;

    self.location = 0;
    self.level = 1;
    self.xp = 0;
    self.inFight = false;

    // add methods that calculate XP and so on
}

function Game() {
    var self = this,
        player = new Player(),
        $playerSprite = $("<img>", {
            "class": "onTop displayCurrentHealth",
            "src": "http://3.bp.blogspot.com/-kAhN0HX-MBk/T_5bApfhbJI/AAAAAAAAAuI/lUww8xT9yV8/s1600/smileys_001_01.png",
            "alt": "you"
        }).data("model", player);

    self.printPlayer = function () {
        $("#" + player.location).append($playerSprite);
    };

    // init
    self.printPlayer();
}
Sign up to request clarification or add additional context in comments.

5 Comments

the code seems ok but i dont know how do later access the .data() here is my attempt - jsfiddle.net/akF2v/1 and jsfiddle.net/akF2v/2 i get [object Object] with $playerSprite.data() but undefined with $playerSprite.data().inFight
You must use event delegation to bind to events on elements that do not exist (or are not yet attached to the DOM). jsfiddle.net/akF2v/3
i got it right i used $playerSprite.data().model.inFight see this fiddle - jsfiddle.net/akF2v/4 (it wasn't the delegation - btw i use delegation in my actual game) thanks though
This is not the correct way to use .data(). It works but is undocumented, so it might break without warning in some future version of jQuery. Plus it's not significantly better than the documented way, so I recommend you use that instead.
you mean use $playerSprite.data("model").inFight instead of $playerSprite.data().model.inFight? - jsfiddle.net/akF2v/5 cause i am gonna use it that way (i discovered it after my post)
1

Don't attach data() to any of your DOM nodes. You should have an object that is aware of it's DOM nodes, as well as a Model. Your monsters can also get access to the Model so they know how much health is left on the player.

It's very rare you'd need to use data() to pass info around. It will make it more difficult to keep your app updated, especially if you want to tweak the DOM later.

Keep your DOM and business logic as separate as possible to keep flexibility up.

var Model = Function( id ) {
 this.health = 100;
 this.id = id;
};

// This object is showing examples of different ways an object can know about the image
var Monster = Function( hero_model, monster_model ) {
  this.sprite = $('#element').tmpl({}); // using jQuery template
  this.sprite = $('<img src="">'); // if you are making image based on model data
  this.sprite = $('#img-' + hero_model.id ); // if you wanted to  look on DOM then, based on data passed in
  this.sprite = document.getElementById( 'img-' + hero_model.id ); // to get element without jquery
};

var Player = Function( model ) {
 this.model = model;
}


// Passing 1 as ID, but you can have a number that increments
var hero_model = new Model( 1 );
hero_model.damage = 50;

var monster_model = new Model( 1 );
monster_model.damage = 10;

var hero = new Player( hero_model );

var monster = new Monster( hero_model, monster_model );

11 Comments

and how do i do that?
You are close using objects. Essentially you want an object that is just for having the data, which is the model. When you initialize the player object you have, pass in the model. The same should go for all the monsters. Since you are using objects, if you modify the values in on one spot, it will be the same everywhere ( all monsters and the player ) since objects are passed by reference.
yes i know that and i do use objects for the monsters as well, i want to know how to connect the object to their html <img> (see title)
Do you have code for the monster object and how the markup gets onto page? Are you using a template engine? That would be the easiest.
i am using all my own (im making games to help teach myself) the monsters are a array of objects created in a function triggered by a loop. (example for (foo) monster[i] = new create(); create(){ this.foo = "bar";} )
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.