4

I started building an Idle Game (like cookie clicker - but so much worse!) in TypeScript. I am new to TypeScript, and mostly JavaScript too.

The issue came up when I changed "cost" from a number, to type "Cost". The idea behind cost being that some later objects (like the winged rat), would cost several resources, and not just scrap. I suspect my implementation of Cost is going wrong somewhere, or the constructor is not built right. Or it's not instantiated correctly.

Currently, when checking "resourceList["rat"].cost.costList["scrap"]", it comes back as undefined. This leads to the "rat" button staying disabled forever.

class Resource {
    name: string;
    amount : number;
    cost: Cost;
    value: number;
    display() : string
    {
        if(this.amount - Math.floor(this.amount) > 0)
        {
            return this.amount.toFixed(2);
        }
        else
            return this.amount.toString();
    }
}

class Cost {
    costList: { [id: string] : number; } = {};
    constructor(res:string[], cost:number[]){
        var i = 0;
        for(var r in res)
        {
            var c = cost[i];
            this.costList[r] = c;
            i++;
        }
        return this;
    }
}

class Scrap extends Resource {
    constructor(public amount) {
        super();
        this.name = "scrap";
        this.cost = new Cost([""],[0]);
        document.getElementById('scrapLbl').innerHTML = this.name + ": ";
    }
}

class Rat extends Resource {
    constructor(public amount) {
        super();
        this.name = "rat";
        this.cost = new Cost(["scrap"],[10]);
        this.value = 1;
        document.getElementById('ratLbl').innerHTML = this.name + ": ";
    }
}

class wRat extends Resource {
    constructor(public amount) {
        super();
        this.name = "wrat";
        this.cost = new Cost(["scrap", "rat"],[10, 1]);
        this.value = 1;
        document.getElementById('wratLbl').innerHTML = this.name + ": ";
    }
}

var resourceList: { [id: string] : Resource; } = {};
var curScrap = new Scrap(0);
var curRat = new Rat(0);
var curWRat = new wRat(0);
resourceList["scrap"] = curScrap;
resourceList["rat"] = curRat;
resourceList["wrat"] = curWRat;

function updateView()
{
    document.getElementById('scrapId').innerHTML = resourceList["scrap"].display();
    document.getElementById('ratId').innerHTML = resourceList["rat"].display();
    if(resourceList["scrap"].amount >= resourceList["rat"].cost.costList["scrap"])
    {
        document.getElementById('scrapRat').disabled = false;
    }
    else
    {
        document.getElementById('scrapRat').disabled = true;
    }
    document.getElementById('ratId').title = resourceList["rat"].cost.toString();
}

function updateValues()
{
    if(resourceList["rat"].amount > 0)
        resourceList["scrap"].amount += (resourceList["rat"].value * resourceList["rat"].amount)/10;
}

function collectScrap()
{
    resourceList["scrap"].amount += 1;
}

function scrapRat()
{
    //cost
    resourceList["scrap"].amount -= resourceList["rat"].cost.costList["scrap"];
    //create
    resourceList["rat"].amount += 1;
    //update cost
    resourceList["rat"].cost.costList["scrap"] *= 1.12;
}

window.setInterval(function(){
    this.updateValues();
    updateView();
}, 100);

Not sure if you need the HTML, but here it is:

<!DOCTYPE HTML>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Scrap Clicker</title>
    <link rel="stylesheet" href="css/bootstrap.min.css" media="screen">
    <script src="js/jquery-2.2.1.min.js"></script>
    <script src="js/bootstrap.min.js"></script>
</head>
<body>

<label id="scrapLbl" ></label> <span id="scrapId">0</span>
<label id="ratLbl" ></label> <span id="ratId">0</span>
<label id="wratLbl" ></label> <span id="wratId">0</span>
<div>
    <button title="Free" data-toggle="popover" data-trigger="hover" data-content="Dig!" class="btn btn-lg btn-primary" onclick="collectScrap()">collect scrap</button>
    <button title="10 Scrap" data-toggle="popover" data-trigger="hover" data-content="Strap some scrap to a rat, now you've got a Scrap-Rat!" class="btn btn-lg btn-primary" onclick="scrapRat()" id="scrapRat" disabled>scrap rat</button>
    <button title="10 Scrap, 1 rat" data-toggle="popover" data-trigger="hover" data-content="Strap some scrap to a Scrap-Rat, now you've got a Flying-Scrap-Rat!" class="btn btn-lg btn-primary" onclick="wRat()" id="wRat" disabled>Winged scrap rat</button>

</div>
<script src="game.js"></script>
<script>
    $(document).ready(function(){
        $('[data-toggle="popover"]').popover();
    });
</script>
</body>
</html>

Bonus Points: Show me a better way to keep track of resources and costs!

3
  • At a quick glance, you have var i = 1. Indexes start at 0, so the first item in the cost array will be skipped, and the last item will be undefined. Commented Mar 11, 2016 at 20:27
  • @cdbajorin Oh, thats weird - rookie mistake. But still didn't fix the issue. Edited the question to change i=0; Commented Mar 11, 2016 at 20:30
  • @cdbajorin That did open it up somewhat. "resourceList["rat"].cost.costList" now returns an Object {0: 10}. Still not sure why I can't reach it with ["rat"] Commented Mar 11, 2016 at 20:34

1 Answer 1

4

Your issue isn't in the typescript, but in your for..in loop:

let myArray = ["a", "b", "c"]
for (var item in myArray) {
    console.log(item);
}
// 0,1,2

"item" is really "index" when using a for...in loop on an array. You want your Cost class to be:

class Cost {
    costList: { [id: string] : number; } = {};
    constructor(res:string[], cost:number[]){

        for (let i = 0; i < res.length; i++) {
            this.costList[res[i]] = cost[i];
        }
    }
}

EDIT: In regards to your bonus points, a more typescript-y way of implementing Cost would be to use an interface:

interface Cost {
    [key: string]: number;
}

class Resource {
    cost: Cost;
    //...
}

class Rat extends Resource {
    constructor(public amount) {
        super();
        this.cost = <Cost>{
            "scrap": 0
        };
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is so awesome! Wish I could +1 you more for that bonus!

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.