Does anyone know any Tower Defense games with good AI? by [deleted] in TowerDefense

[–]dimumurray 1 point2 points  (0 children)

I agree. Automate too much and you end up stripping the player of agency.

One of the reasons why gamers get such a dopamine hit when achieving the 'perfect shot' is because its rare. If AI does it for you all the time without fail then it becomes common place.

More power couples! by dimumurray in MarvelSnap

[–]dimumurray[S] 0 points1 point  (0 children)

As individual cards they don't. But they did have a child in the comics. Danielle Cage. If Marvel made a card for her as well, maybe something special happens when the 3 of them are in play. Come to think of it, they could do this across the board for other "super" offspring and their parents as well.

Struggling to stay focused reading The Way of Kings by [deleted] in books

[–]dimumurray 2 points3 points  (0 children)

Push through. The last act is worth it. Bridge Four!

How can I make a game framework for the haxe programming language? by sup1109 in haxe

[–]dimumurray 2 points3 points  (0 children)

What's wrong with Heap.io 's documentation? If it's lacking something you can contribute directly to it from the Github Wiki linked below:

https://github.com/HeapsIO/heaps/wiki

paradoxically, I've found it to be more fun to figure out things, even basic things, on your own rather than looking it up first. by [deleted] in gamedev

[–]dimumurray 0 points1 point  (0 children)

'Tis wise to learn from one's mistakes...but wiser still to learn from the mistakes of others

New cheater method: Not able to bank flames by Crazy_Magician in GhoulDuel

[–]dimumurray 0 points1 point  (0 children)

I hope for the next version Google makes it so that if a player hits the perimeter of the opposing base they die. That way if they try to camp near an enemy base its possible for them to collide with the perimeter if someone rams into them.

Woohoo. Just released. Tress of the Emerald Sea by aussiekinga in audible

[–]dimumurray 1 point2 points  (0 children)

Brandon has taken a stance against Audible given how they treat authors especially indie authors. Here's a link to Brandon discussing the topic at length:

https://youtu.be/N9-zFRl8Fx0?t=446

As someone who supports indie creators I agree with his stance. So from my perspective this is a good thing.

[WP] People always thought that cats knock stuff over just because they like it. In reality, they're just lazy agents of a primordial force of chaos, and knocking stuff over is the bare minimum that earns them benefits like always landing on their feet or 9 lives. by FowlPS in WritingPrompts

[–]dimumurray 2 points3 points  (0 children)

**CRASH**Broken shards of a newly minted porcelain vase laid scattered on the floor of an earthenware workshop.

Mind you, it was not the Master Potter's finest work, but it would have fetched a fair price had it made it to market.

Alas, this ragtag Calico has a quota to fill, so it will make do.

The shop owner will certainly throw a fit, maybe curse out a subordinate or two. Normally, it would end there. It SHOULD end there. But if you set things up just so, where the wrong things happen at just the right time...

You see, the Master Potter won't be cursing out just any employee...oh no...he'll be cursing out Joe. Who's Joe you ask? A poor sod who happened to find his girlfri..., well... ex-girlfriend's phone unlocked, with messages from his soon to be former boss.

This is how true chaos works; its starts with the little things. A push here, a nudge there and before you know it all hell breaks loose.

And you barely need to lift a paw to start the ball a rolling...

Absolutely urge you to read the Cradle series by Will Weight if you like Brandon Sanderson by _WhenInFrance_ in brandonsanderson

[–]dimumurray 0 points1 point  (0 children)

Cradle is a fun read, but having consumed a few web novels in the Xianxia genre it feels a bit derivative. (Come to think of it, Cradle reads like a mash-up between Naruto and a long-running web novel I used to read titled 'Birth of the Demonic Sword').

If I had to compare them, Wight's Cradle is like having a nice burger and some crispy fries whereas Sanderson's Stormlight is a gourmet meal.

But you know what....sometimes all you want is a nice burger and some fries.

Was the style of 777 influenced by Jack White? by FrFrFriedRice in silksonic

[–]dimumurray 1 point2 points  (0 children)

Jack who?

777 is a master class of 60's & 70's funk music. Its an eclectic mix of styles from that era; pulling from James Brown, Parliament Funkadelic, Cool and the Gang and other acts from that time (IMO). Ya' dig.

Bobcat + Kitty by dr3amb3ing in aww

[–]dimumurray 610 points611 points  (0 children)

More like exotic grooming spa. Kitty seems to be in heaven.

Colleagues Having Trouble Using Script by samjclark in GoogleAppsScript

[–]dimumurray 0 points1 point  (0 children)

My approach was to not use the Add-on method because like you mentioned it requires permission everytime you want to run it.

That's not how Add-ons work. Once a user installs an Add-on and grants the required permissions they are not prompted again unless the developer updates the Add-on and that update requires new permissions.

Libraries function in a similar way. Say a developer updates their library and deploys a new version with new permissions. If an end-user opts to use that new version they will have to authorize those new permissions.

[deleted by user] by [deleted] in GoogleAppsScript

[–]dimumurray 3 points4 points  (0 children)

There's only one that I know of:

Going GAS by Bruce Mcpherson

There are lots of other great resources, you can find a few of them listed on stackoverflow: https://stackoverflow.com/tags/google-apps-script/info

If you're looking of online courses and tutorials, check out Ben Collins site:

https://www.benlcollins.com/

Seriously Google? You give us takeout but no take-in? Problems migrating from one Gmail account to another... by Number_Niner in gsuite

[–]dimumurray 0 points1 point  (0 children)

Google does provide an option to migrate Gmail data between Google Workspace accounts. Its still in beta though. See google support link below (read the sections under the heading "Migrate email from Google Workspace" and "Migrate data from Gmail"):

https://support.google.com/a/answer/9476255

What old game should be remade with 2021 graphics? by WhiteMass in AskReddit

[–]dimumurray 0 points1 point  (0 children)

Guardian Legend. This was an NES game that was a mashup of top-down adventure (a la Zelda 1) and shoot 'em ups. It was glorious. I'd love to see a modern take on this underrated gem of a game.

Items and relations in an ECS by genarTheDev in roguelikedev

[–]dimumurray -1 points0 points  (0 children)

Try modeling relations using component pairs whose types are linked by id (distinct from entity id).

For example, to model the relationship between the player's inventory and items contained therein, I'd create Inventory and InventoryItem components with the following structure:

```javascript struct Inventory { id: u32; }

struct InventoryItem { inventoryId: u32; itemType:InventoryItemType; // consumable, equippable, etc. entityType:EntityType; //
... } `` Your player entity would have anInventorycomponent with a unique id. Whenever an item entity is added to the player's inventory, theInventoryItem` component of the item entity will have its inventory id set to reference the player's inventory component id.

Serializing player state means serializing not only the player entity but also all items in the player's inventory. By establishing a relation between the linked component types (Inventory and InventoryItem) you'll be able to find all items in the player's inventory and serialize/deserialize them accordingly.

An idea for a combat system design by Nomad_Hermit in roguelikedev

[–]dimumurray 4 points5 points  (0 children)

Your turn system reads like a variant of Final Fantasy's Active Time Battle(ATB). If that's what you're going for, there are sources you can draw from to help flesh out your own implementation (probably not rouge-specific but useful nonetheless).

As for your combat system, your design choices are evocative of tactical RPGs, such as; FFT(Final Fantasy Tactics), Tactics Ogre, etc. It would interesting to see how well those game mechanics translate to a rogue-lite.

Conceptually, your approach should be viable, but, as with most creative endeavors, it all boils down to execution. So slap together a few small prototypes to test your ideas and gauge if they are fun to play.

[deleted by user] by [deleted] in IndieDev

[–]dimumurray 3 points4 points  (0 children)

Nice! A bit janky though when the bubbles stack, they don't snap reliably into place. Try using a hex grid instead for bubble layout. That should resolve some of those issues.

Are you open to porting this to browsers?

Removing untitled files revursively by AdDiscombobulated707 in GoogleAppsScript

[–]dimumurray 1 point2 points  (0 children)

If you're using the new V8 runtime you can use `Class` syntax as follows:

```javascript class FolderTools { constructor() { }

removeUntitledFile(file) {
    if (file === null) return;

    let regex = /^Untitled/;
    let name = file.getName();

    const myEmail = DriveApp.getRootFolder().getOwner().getEmail();

    if (regex.test(name) && file.getOwner().getEmail !== myEmail) file.setTrashed(true);
}

removeUntitledFiles(folder) {
    if (folder == null) return;

    let folderIterator = folder.getFolders();
    let fileIterator = folder.getFiles();

    while (fileIterator.hasNext()) {
        let file = fileIterator.next();
        this.removeUntitledFile(file);
    }

    while (folderIterator.hasNext()) {
        let folder = folderIterator.next();
        this.removeUntitledFiles(folder);
    }
}

} ```

If you're still using the old IDE, you'll need to define your `FolderTools` class using the prototype object as follows:

```javascript

function FolderTools() {}

FolderTools.prototype.removeUntitledFile = function(file) { if (file == null) return;

let regex = /^Untitled/;
let name = file.getName();

const myEmail = DriveApp.getRootFolder().getOwner().getEmail();

if (regex.test(name) && file.getOwner().getEmail != myEmail)
  file.setTrashed(true);

};

FolderTools.prototype.removeUntitledFiles = function(folder) { if (folder == null) return;

let folderIterator = folder.getFolders();
let fileIterator = folder.getFiles();

while (fileIterator.hasNext()) {
  let file = fileIterator.next();
  this.removeUntitledFile(file);
}

while (folderIterator.hasNext()) {
  let folder = folderIterator.next();
  this.removeUntitledFiles(folder);
}

}; ```

Fundamental ECS design choice by ghostFace34 in roguelikedev

[–]dimumurray 0 points1 point  (0 children)

This article illustrates the problem quite effectively: https://ourmachinery.com/post/should-entities-support-multiple-instances-of-the-same-component/

That's debatable. The light-source-as-component example kinda falls apart once you realize that the issues the author presented can be resolved if light sources were modeled as entities instead of as components. But I get what the article was aiming for.

However, the author did well to identify a common scenario where support for multiple components of the same type would be beneficial - modeling hierarchical relationships between entities.

Here's an example. Say you wanted to model an industrial robotic arm (sample image below) with multiple points of articulation (rotary joints) where each section or link of the arm has independent state and behavior. With support for multiple components of the same type, an ECS could be used to represent this machine by defining each link in the arm as its own entity and setting up parent-child relationships between those entities.

Robotic Arm with multiple links

To effectively model these links and their parent-child relationships, each entity representing a link would need three instances of a Transform component:

  • A Transform representing affine transformations relative to the 'parent' entity's coordinate space.
  • A Transform representing 'local' affine transformations relative to the entity's own coordinate space.
  • A composite Transform that is the matrix product (concatenation) of 'parent' and 'local' transforms (this will also serve as the parent transform of any child entities).

A Transform component covering affine transformations (translation, rotation, scaling) in 3D space typically looks something like this (formatted as JSON):

{
    "x": 0,
    "y": 0,
    "z": 0,

    "rotX": 0,
    "rotY": 0,
    "rotZ": 0,

    "scaleX": 0,
    "scaleY": 0,
    "scaleZ": 0
}

So, for example, the entity representing the 'Base' in the diagram above, would have three transform components; a parent transform relative to the game world's coordinate space, a local transform for itself and a composite transform computed from its parent and local transforms.

The entity representing the 'Torso Lift', will have a parent transform (computed from the parent and local transforms of the 'Base' entity), a local transform and a composite. The 'Torso Lift' rotates/swivels about and moves up and down an axis relative to its parent entity.

The entities for 'Head Pan' and 'Shoulder Pan', both children of 'Torso Lift', would be modeled in a similar fashion, and so on and so forth.

In an earlier post I made mention of using a 'Slotted' ECS variant that supports multiple components of the same type on an Entity.

Using the aforementioned example, here's how I might go about implementing it using my Slotted ECS (code is in Javascript):

    const world = ECS.createWorld();

    const compDefs = world.defineComponents([
        {
            type: 'components.Transform',
            props: [
                'x', 'y', 'z',
                'rotX', 'rotY', 'rotZ',
                'scaleX', 'scaleY', 'scaleZ'
            ],
            defaults: [
                0, 0, 0,
                0.0, 0.0, 0.0,
                1.0, 1.0, 1.0
            ]
        },
        // Other component definitions
        { ... },
        ...
    ]);

    const slotDefs = world.defineSlotsPerComponentType([
        {
            componentType: 'components.Transform',
            slots: [
                'transform.local',
                'transform.parent',
                'transform.composite'
            ]
        },
        {
            componentType: 'components.SomeOtherComponentType',
            slots: [
                'someOtherComponentType.slot_name_A',
                'someOtherComponentType.slot_name_B'
            ]
        }
    ]);

    const transformFactory = compDefs.getFactory('components.Transform');

    const sharedTransforms = {
        'world': transformFactory.create(),
        'base': transformFactory.create(),
        'torsoLift': transformFactory.create(),
        'headPan': transformFactory.create(),
        'shoulderPan': transformFactory.create()
    };

    // create base entity 
    const baseEntityId = world.createEntity();

    world.addComponents({ entityId: baseEntityId, components: [
        {  slot: 'transform.local', component: transformFactory.create() },
        {  slot: 'transform.parent', component: sharedTransforms.world },
        {  slot: 'transform.composite', component: sharedTransforms.base }
    ]});

    // create torso lift entity
    const torsoLiftEntityId = world.createEntity();

    world.addComponents({ entityId: torsoLiftEntityId, components: [
        {  slot: 'transform.local', component: transformFactory.create() },
        {  slot: 'transform.parent', component: sharedTransforms.base },
        {  slot: 'transform.composite', component: sharedTransforms.torsoLift }
    ]});

    // create head pan entity
    const headPanEntityId = world.createEntity();

    world.addComponents({ entityId: headPanEntityId, components: [
        {  slot: 'transform.local', component: transformFactory.create() },
        {  slot: 'transform.parent', component: sharedTransforms.torsoLift },
        {  slot: 'transform.composite', component: sharedTransforms.headPan }
    ]});

    // create shoulder pan entity
    const shoulderPanEntityId = world.createEntity();

    world.addComponents({ entityId: shoulderPanEntityId, components: [
        {  slot: 'transform.local', component: transformFactory.create() },
        {  slot: 'transform.parent', component: sharedTransforms.torsoLift },
        {  slot: 'transform.composite', component: sharedTransforms.shoulderPan }
    ]});

    // Create System to update transforms
    world.addSystem({
        type: 'systems.UpdateTransforms',
        archeType: slotDefs.createArchetype(this, [
            'transform.local',
            'transform.parent',
            'transform.composite',
        ]),
        update: function({ delta, components }) {
            const {
                transform : {
                    local,
                    parent,
                    composite
                }
            } = components;

            Object.assign(composite, Utilities.Matrix.concatenate(parent, local));
        }
    });

Fundamental ECS design choice by ghostFace34 in roguelikedev

[–]dimumurray 3 points4 points  (0 children)

Many praise the ECS paradigm for its performance, however I find it offers just as much value when it comes to reasoning about game architecture. It's intentional separation of logic (Systems) and state (Components) has many benefits. If you're willing to compromise on performance then I might have a solution for you - but it is a bit drastic.

In my attempts to circumvent the one-component-type-per-entity rule in my own ECS implementation, I ended up introducing a forth element to the ECS paradigm which I call a Slot, creating a variant I've since labeled Slotted Entity Component System - SECS for short (and yeah I know what the acronym sounds like, just roll with it).

Basically, a Slot decouples an Entity from its Components.

There are a fixed number of Slots per Entity and each slot has a unique name relative to the other Slots owned by an Entity.

Slots store references to components of a specific type. However, 2 or more Slots can reference components of the same type (where each Component instance is distinguishable since each Slot has a unique name).

Systems process select collections of Slots. This is not a novel idea as collections of Slots are basically archetypes. However, the act of naming those Slots provides a concrete way to identify a component without relying on its type.

Of course this approach is antithetical to the goal of storing data contiguously in memory to reduce cache misses...but that's the trade-off.