Jump to content

Chief

Members
  • Content Count

    64
  • Donations

    $0.00 
  • Joined

  • Last visited

  • Days Won

    1

Chief last won the day on November 26 2016

Chief had the most liked content!

1 Follower

Profile Information

  • Gender
    Not Telling

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. I've proven out my game engine/framework and I now need your help in defining the core functionality to program into it. You can freely contribute to the document below: https://docs.google.com/document/d/1qc_GzFmv5OsqJs0IDwe4wJR0lJg5uLpnS_SQE6CTzd4/edit?usp=sharing Now that I've built the underlying engine and am now just focused on building out features, I expect that this engine will actually be completed.
  2. Thinking about it now, I think one component per attribute is the right way to go about it. It makes it super easy to generate a game from data. In other news, I've completely rewritten everything. I've turned it into a library that you can find here: https://github.com/eclipse-games/encosy -- the following are real, working examples, utilizing the library: Component (Position) import { Component } from '@eclipse-games/encosy' export default new Component({ x: Component.types.number, y: Component.types.number, z: Component.types.number }); Entity (Character) import { Entity } from '@eclipse-games/encosy'; import Position from '../components/position'; import Size from '../components/size'; import Texture from '../components/texture'; export default new Entity({ position: Position, size: Size, texture: Texture }); System (Render) import { System } from '@eclipse-games/encosy'; import state from '../core/state'; import Position from '../components/position'; import Size from '../components/size'; import Texture from '../components/texture'; export default new System([ Position, Size, Texture ], (world, entity) => { const position = world.components.get(Position).get(entity); const size = world.components.get(Size).get(entity); const texture = world.components.get(Texture).get(entity); state.drawContext.drawImage(texture.data, texture.clip.x, texture.clip.y, texture.clip.width, texture.clip.height, position.x, position.y, size.width, size.height ); }); I think I got the concept fully down now, and am pretty pleased with the outcome of this weekend curiosity. Definitely let me know your thoughts on ECS vs OOP.
  3. I've made some modifications to my concepts to improve performance. The first is of entities; they are no longer each their own class; now they're just a module with a create method that instantiates an Entity; making all entities an instance of a single class allows the JS engine to optimize storing them in memory, and also simply means less classes. import Entity from '../core/entity'; import Position from '../components/position'; import Size from '../components/size'; import Texture from '../components/texture'; export default { create (world, { position, size, texture }) { const character = new Entity(); world.entities.add(character); world.components.get(Position).set(character, new Position(position)); world.components.get(Size).set(character, new Size(size)); world.components.get(Texture).set(character, new Texture(texture)); return character; } } The next optimization is of services. You now instantiate a Service with a list of required components and a function that will be called if all required components exist for that entity. I also made it so services only take one entity at a time so you need to loop through all entities beforehand, which means looping over them far less frequently, increasing runtime performance. import System from '../core/system'; import Position from '../components/position'; import Size from '../components/size'; import Texture from '../components/texture'; export default new System([ Position, Size, Texture ], (world, entity) => { const position = world.components.get(Position).get(entity); const size = world.components.get(Size).get(entity); const texture = world.components.get(Texture).get(entity); world.state.get('drawContext').drawImage(texture.data, texture.clip.x, texture.clip.y, texture.clip.width, texture.clip.height, position.x, position.y, size.width, size.height ); }); As you can see, the first argument is an array which contains the required components. You run a system by calling its run method, which will check for the existence of components of an entity, like so: export default class System { constructor (mask = [ ], action = (() => null)) { this.mask = mask; this.action = action; } run (world, entity) { const { components } = world; if (this.mask.reduce((prev, next) => prev && components.get(next).has(entity), true)) { this.action(world, entity); } } } No modifications have been made to components, as they're still just data. The next concept I want to explore is instead of having one component per character attribute (health, experience, magic, etc), finding some way to have a generic Attribute component, but I'm not sure how that will work quite yet.
  4. In the past, I have always written games/engines in full-on OOP, but I stumbled upon an architecture that purports to be widely used when it comes to games, which I'm sure you are all aware of, but I was not. Entity/Component architecture is supposed to help with issues of having large hierarchies of inheritance when it comes to entities, like a character. Following this article from Gamedev.net (https://www.gamedev.net/resources/_/technical/game-programming/implementing-component-entity-systems-r3382), I've recreated what I understand to be an Entity/Component architecture in JavaScript. First of all, the article created a core World object that contains a list of all current entities in the game, and then weak maps (I'll explain this momentarily) of the components of each entity. In JavaScript, this looks like the following: import Position from '../components/position'; import Size from '../components/size'; import Texture from '../components/texture'; const { Map, Set, WeakMap } = global; export default class World { options = new Map(); state = new Map(); entities = new Set(); components = new Map([ [ Position, new WeakMap() ], [ Size, new WeakMap() ], [ Texture, new WeakMap() ] ]); } As you can see, components is a Map of <ComponentClass, WeakMap>. What a WeakMap allows, is that if the key exists nowhere else in memory, the WeakMap will allow it to be garbage collected. The WeakMap is essentially <Entity, Component>, so if the entity is deleted from the world's entities Set, then it will automatically be garbage collected, preventing memory leaks. The second part of this architecture is a Component. Components are strictly made up of data, and combined together as a group, make up an Entity. A simple example of one in JavaScript would be as follows: export default class Position { constructor ({ x, y, z = 0 }) { this.x = x; this.y = y; this.z = z; } } The third concept, of course, is an Entity. Now, an Entity isn't actually anything more than an identifier that components reference in order for services to work (I'll cover services next). Basically, Entity/Component architecture prefers composition, so I have a create method that takes configuration, and creates components. In JavaScript, this looks like: import Position from '../components/position'; import Size from '../components/size'; import Texture from '../components/texture'; export default class Character { static create (world, { position, size, texture }) { const character = new Character(); world.entities.add(character); world.components.get(Position).set(character, new Position(position)); world.components.get(Size).set(character, new Size(size)); world.components.get(Texture).set(character, new Texture(texture)); return character; } static delete (world, character) { world.entities.delete(character); } } You can see that Character is still a class, and is instantiated inside of the static create method, but this is simply to create a unique entry in memory that the services can correctly find all of the components of an entity. The most complicated (it's not complicated) part of this architecture are the services. Services are just functions that you call that act upon entities. An example of a render services looks as follows: import Position from '../components/position'; import Size from '../components/size'; import Texture from '../components/texture'; export default function render (world) { const { components, entities, state } = world; for (const entity of entities) { const position = components.get(Position).get(entity); const size = components.get(Size).get(entity); const texture = components.get(Texture).get(entity); if (!position || !size || !texture) { continue; } state.get('drawContext').drawImage(texture.data, texture.clip.x, texture.clip.y, texture.clip.width, texture.clip.height, position.x, position.y, size.width, size.height ); } } As you can see, for each entity, it checks if that entity has the required components, which in this case are Position, Size, and Texture. If all three exist, it uses the data from those components to draw the entity onto our canvas, using the drawContext. To all who are familiar with this architecture and OOP; does this seem right to you? Have you used Entity/Component architecture before? Do you prefer OOP?
  5. Chief

    Looking for Alpha Testers

    PM sent; thanks for offering your help!
  6. Chief

    Looking for Alpha Testers

    Anybody else want to help? This is the last call; I'll be opening the forums for a more public alpha in a couple of weeks.
  7. Chief

    Crest for hire

    Dyldo2 is the best programmer I know. If funds weren't so tight right now (just dropped 3k on adult bills and car things), I would totally hire him.
  8. Chief

    Looking for Alpha Testers

    PM sent to you both as well
  9. Chief

    Looking for Alpha Testers

    I'm gonna address a couple of the bugs/features that others have called out so far, then I will send you a PM
  10. Chief

    Looking for Alpha Testers

    Messages sent to you both; I have no reason to not let anybody help me out; I just don't want it to seem like I'm just posting in order to advertise; that's not my goal. I really just want help testing my site.
  11. Chief

    Looking for Alpha Testers

    Message sent
  12. I've been working on a website 100% from scratch using Node.js for the back-end (with Postgres and Redis), and then React for the front-end. I want to launch the forums in an alpha state within the next couple of weeks, and I need a handful of people to run through a simple process of joining and posting, and then giving me as much feedback as possible. If you're interested, reply here, and I'll shoot you a PM with a URL and instructions.
  13. Chief

    Exactly.

    Exactly
  14. Chief

    Spookiest things that happened to you?

    I have no idea if the kid is mine. Does it weird me out that it's possibly mine? A little bit, but the kid has two seemingly loving parents, so it's no big deal.
×