LGV

Members
  • Content count

    16
  • Joined

  • Last visited

  1. Thanks, 'much appreciated ! If I am not mistaken, I believe we talked about game frameworks, ECS infrastructures, data-driven entities, etc. a while ago ; have you posted / presented your own project ? I'd love to have a look too !
  2. Many thanks ! It's hard to keep a dynamic without a big community, so anything that helps is greatly appreciated The artists will be pleased about the art feedback !
  3. Thanks, much appreciated We'll see how things go in terms of "greenlight-ing" !
  4. Hi all, I am here to present Relic : Tale of the Undead Princess, a retro 2D action-adventure game. On the menu : Greenlight, trailers, playable demo and upcoming release ! OVERVIEW The princess is dead... But she is back ! The last hope against evil forces. Help her explore the realm and succeed where all heroes have failed. Relic : Tale of the Undead Princess is a retro 2D action-adventure game, with a fine blend of exploration, puzzles, secrets and challenges ! GREENLIGHT Support the Princess on Steam > Relic on Greenlight < I am not asking for "likes" it, but if you enjoy the concept and gameplay, a little help is always welcome. Thanks More resources on the Steam Greenlight page : trailer, screenshots, features and playable demos. DEVELOPMENT I work alone and I handle the programming, production, game design, level design, QA and misc art assets ; for everything else (main tilesheets, sprites, music) I license asset packs from artists and asset stores. Full detailed credits in the game. - Estimated play time : 8~12h, depending on player experience and game completion - Game size : ~200 playable screens - Team : myself ! - Development time : ~1 year, from scratch - Platforms : Windows 7/8/10, Linux (tested on Ubuntu 16.04 LTS) - Release date : TBC ~ Spring 2017 TOOLS - Tech : The game is developed in TypeScript, using VSCode and SmartGit. It is using the Phaser engine, in its latest pre-CE version, 2.6.2. On top of which I add my own gameplay framework, a json data-driven Entity-Component-System architecture. - Art & design : I'm using Pyxel for misc pixel art and Tiled for the level design. - Production : handled with Trello and Toggl, plus a collection of ad-hoc prod assets. - Shipping : The application is packaged with NW.js to deploy as a desktop executable. Thanks for reading - I hope you will enjoy Relic : Tale of the Undead Princess !
  5. Hi all ! I am rendering tilemap layers to textures, but I have issues applying a "camera" offset to get the correct area of the layer to appear in the texture. In this setup, the actual world/scene is only made of 1 single sprite covering the entire game window and displaying the content of the rendertexture. The game/world camera is static (0, 0). Only the content of the rendertexture is updated to reflect the player moving around. (The goal is to do some fancy post-processing using the rendertexture, including custom up-scaling) My problem is that I can't seem to find the right combination of layer parameters to get a subset of the layer to render into the texture :-? I've created a minimal test scene that demonstrates the problem : http://phaser.io/sandbox/edit/weeeaLZy function create() { // Create a render texture the size of the game window texture = game.make.renderTexture(game.width, game.height); // Adds a sprite using the render texture to the scene game.add.sprite(0, 0, texture); // Create the tilemap var map = game.add.tilemap('Map'); map.addTilesetImage('CybernoidMap3BG_bank.png', 'Tiles'); // A layer is added to a dummy group, not to be included in the default World // The layer is rendered onto the render texture manually in the update() group = game.make.group(null); layer = map.createLayer(0, game.width, game.height, group); // Custom arbitrary "camera" offset ; this would driven by gameplay logic (player position, etc.) var camX = 64; var camY = 64; // Attempt at getting the tilemap layer to render according to manual offset. These values seem ignored when rendering to texture :-? layer.fixedToCamera = true; layer.cameraOffset.x = -camX; layer.cameraOffset.y = -camY; } The only relevant topic/example I found is this demo : http://phaser.io/examples/v2/display/render-texture-tilemap , doing a manual layer render by processing all the tiles manually... Which I'd really like to avoid, because of massive drawcalls overhead. I've tried lots of things, cropping, render offset, etc. so far nothing gave the expected result :-? Any help would be greatly appreciated ! Regards
  6. Quick update, in case anyone cares or find this topic while facing a similar issue ; this seems to be a bug in the version of Phaser I'm using and appears to be fixed in the latest 2.6.1 : I've re-created a test sample in the online editor and this seems to behave as expected : http://phaser.io/sandbox/edit/dFJUoMIL
  7. And just to illustrate things a bit clearer, a couple of screenshots demonstrating the pixel processing I'm doing. Note that since I'm stuck with Tilemap Layers not rendering to render textures, this is just my shader working on a static picture of the game I exported to a small test environment - Base picture ; simple "nearest" scaling x3 Processed picture : some minor colour adjustment (vibrance, brightness, etc.), scanlines, and the manual upscaling (a simpler ~EPX3x in this case) As soon as I figure out how to deal with Tilemap Layers I'm hoping to get this live on my game !
  8. Additionally, while I'd rather do the upscaling myself (w,h) => (4*w, 4*h), I could probably achieve what I want if I could work on the "phaser-upscaled" image ; in case there's an alternative solution to my problem... Still, I'm curious about the use of tilemap layers in group containers :-?
  9. Hi all ! I'm having some issues with getting tilemap layers to render to textures if added to custom groups instead of the default game.world. Context : I'm working on a top-down pixel-art a-rpg (think Zelda 3-like). I have a mix of tilemap layers and sprites. Nothing too fancy. Goal : I want to implement a custom upscaling shader (e.g. hq4x). I'm changing my scene to draw layers and sprites to a texture, so that I can use that texture with my custom shader. Progress : I can easily get sprites to render to my texture, and using my shader to display that texture also works well Problem : To avoid overhead of individual draw calls per sprite/layer, I use a top-level Group container ; but I can only get tilemap layers to appear if they are added to the game.world and not to my top-level container :-? In my preload() : nothing exciting, just the tilemap (Tiled json), some images/spritesheets, and a shader/fragment In my create() : // The top-level container to hold display objects this.m_group = new Phaser.Group(this.game, null); // The render texture where I want all display objects to appear. Later the size will need to differ from the game size, for the "upscaling" part this.m_renderTarget = this.game.add.renderTexture(g_screenWidth, g_screenHeight, "RenderTarget"); // The actual sprite using the render texture let rtSprite : Phaser.Sprite = this.game.add.sprite(0, 0, this.m_renderTarget); // Sprite test ; this works nicely let sprite : Phaser.Sprite = this.game.make.sprite(0, 0, "Player"); this.m_group.add(sprite); // Layer test ; this does NOT work this.m_map = this.game.make.tilemap("Overworld"); this.m_map.addTilesetImage("Tileset", "Tileset"); this.m_layer = this.m_map.createLayer("Layer", g_gameWidth, g_gameHeight, this.m_group); (I've excluded the shader/filter setup, not relevant for the problem) In my Update() : this.m_renderTarget.renderXY(this.m_group, 0, 0); I was thinking using the 4th parameter "parent" of the createlayer method to add it to top-container would be sufficient. This is not the case. The only way I found to get my layer to appear on my render texture is 1. add the layer to the default game.world, 2. turn off the layer.renderable (because I don't actually want it in the default scene), 3. create a sprite using the layer texture. 4. add the sprite to my container group. Which looks like : this.m_layer = this.m_map.createLayer("Layer"); this.m_layer.renderable = false; let sprite : Phaser.Sprite = this.game.make.sprite(0, 0, this.m_layer.texture); this.m_group.add(sprite); While this is functional, this sounds overly convoluted and non-intuitive, so surely I'm not using the whole thing correctly ! The layer should behave as a display object and I don't understand why it needs to be treated differently :-? Additionally, I tried having a separate rendertexture.renderXY() call for the layer (this.m_renderTarget.renderXY(this.m_layer, 0, 0, true);) ; same problem, the layer only appears if added to the game.world and not to any other container. Any idea what I'm missing or doing wrong ? Any help would be greatly appreciated ! Regards
  10. Quick update regarding progress - I have just completed a first round of focus testing last week (thanks to all the participants !). While still quite far from an actual "demo", this allowed me to answer 2 critical questions : - in spite of the "work in progress" nature of the project, is there sufficient potential to complete & release the game ? - how to prioritise the remaining work in order to maximise the time/player experience ratio ? In light of the feedback, I have recalibrated the production tracking and I plan 3 major iterations : - gameplay : tweak existing elements, redesign weak mechanisms, add missing functionalities, etc. - content : balance existent areas, redesign some puzzles, integrate additional zones, etc. - presentation : scenario / tutorial, graphical polish, options and controls customisation, etc. Including publication delays, I am still planning for a release around ~late Summer 2016 'Will post updates soon with actual concrete progress !
  11. Not usually a problem regarding performance ; if certain types of messages tend to be used A LOT it might interesting to put a recycling pool mechanism in place, to save on the construction of objects - but usually VMs and script engines have some of this built-in already. In a native engine, we'd also compile everything, messages, strings, identifiers, etc. to a binary format. If it ever becomes a problem for performance, it's always possible to refactor specifically bits of the components once a perf killer has actually been identified. I always favor flexibility at first - the time saved in development will be better used for optimisations later on, once we know what the problems are. Alternatively, some people prefer to have all their Components as POD structs (data only, all public, no methods), and use Systems for all the logic. This reduces the messaging to some extent. All variations are viable. 2 "special" Components I really like to have : - a "ScriptComponent" ; basically it's a dummy that just calls custom defined Init/Advance/Receive. Incredibly useful for exclusive puzzles, boss logic, etc. Trivial in JavaScript, just "eval" "objectname" + naming convention (ObjectName_Init, etc.) - a "MapperComponent" ; something to "translate" a message into a different one. It has a mapping table (A1 => B1, A2 => B2, etc.). It can help to reduce coupling between Components messages. Instead of having the AudioComponent process the Death message, just re-map Death message to, say, a "play sfx 'death' " message and have the AudioComponent process PlaySFX messages only
  12. Correct - though you never target a Component directly, you always sent to an Entity ; the Entity dispatches to its Component, and the ones interested in that message can process it (so 1 message can trigger multiple changes, on various Components in parallel) Also, for cases where a Component needs to target its parent Entity, I have a "this.self" initialised when I construct Entities. In my Post system, a Message is a type (via instanceof) and additional data (e.g. amount of damage, etc.), and a Parcel is just a wrapper for a Message (sender, target, delivery method, etc.) So everything is done through chains of message : Entity receives Damage > HealthComponent processes Damage, sends Death message to itself > Entity receives Death > AudioComponent triggers death sound + VisualComponent triggers death particles > Entity removes itself
  13. This should help to visualise the relationships a bit better ; the factory logic itself isn't really visible, since it's what's happening when assembling a Prototype (= partial Components with template bits) with a group of ComponentInstanceData (= partial Components with instance bits)
  14. Thanks for all the feedback - Oh I do have story elements, plots and leads - though it's difficult to find art asserts to really support a proper scenarisation ; I think I'll have to stick to something relatively simple, at least in terms of story-telling, and keep just the few good bits that make the core of it. Regarding the ECS, I'm not familiar with Stencyl and its concept of Actors so I can't really explain how it differs from my own infrastructure. Basically, a Component in my framework has 6 core elements : 3 data bits (template, instance, runtime, cf. previous definitions), and 3 methods : - Init() - Advance(_time) - Receive(_parcel) Every specialised Component (e.g. "HealthStatComponent") inherits from the base Component interface. An Entity is then an abstract object, with just a collection to store Components, and a couple of methods (Advance/Receive) to propagate/dispatch the updates/messages to its Components. For each Component I also have a few "helper" classes to help organise the data when parsing/building definitions : ComponentTemplateData, ComponentInstanceData. When parsing the prototype definitions files and level file, it's just matter of building each data bits for each Component (=> partial Components with only the template data), then parsing the level files (=> partial Components with only the instance data) and finally instanciating the required Components once all the required data is known. In some languages this would rely on some form of custom-typing or RTTI-like mechanism, in TypeScript this is trivial : .json specifies Components name, and the Component factory relies on "eval" string evaluations, and also heavily on instanceof tests when assembling Components (template + instance) to ensure Entities are well-formed Said a bit differently, the construction "flow" goes like this : - read .json definition files (= specifies all components types for every entity, with the common data) => build partial Components, i.e. ComponentTemplateData ; group these into what I call Prototypes (= a collection of partial Components with template data only ; can also be seen as a "partial" Entity, it's an Entity without all the instance data) - store all the Prototypes into a simple database/manager for future look-up - apply Prototype inheritance by propagating partial Components to derived definitions - read the level file => given the Entity type, build partial Components, the instance bits this time, i.e. ComponentInstanceData. - use a factory to assemble it all together : Prototype (= collection of ComponentTemplateData) + collection of ComponentInstanceData = Entity. This also checks for possible mismatch, e.g. trying to assemble partial Components that don't go together, or where bits of data are missing (e.g. no instance x/y specified for PositionComponent). This can happen with typos or incomplete definitions. The process is the same when creating an Entity dynamically during gameplay ; look-up the Prototype (= all the template bits), provide the instance data required by the Entity you're creating (position, etc.), and use the same factory to do the assembling
  15. Thanks - here are some technical details that will hopefully explain things a bit more - My ECS is fairly traditional in terms of architecture : - Entities are abstract high-level objects made of collections of Components - Components are a hybrid mix of data and logic (as opposed to another ECS philosophy where Components are pure data and all logic goes into Systems ; personal preference only) - Systems handle all cross-components and entity-level logic (controls, display, etc.). I don't have that many since quite a lot is delegated to Phaser (collisions, etc.) In parallel, I use a messaging system to handle all entity or component communication. Where it gets more interesting is when we look at the Components factory ; for each Component there are 3 types of data: - prototype data (or blueprint), coming from definition files (json). These are common to all instances of the same Entity (e.g. this type of switch uses these sprites) - instance data, coming from the level file. These are specific to each instance of an Entity (e.g. the position of the switch in the world) - runtime data, extra info required by the logic of the game. Again, specific to each instance but driven by gameplay, not files (e.g. the current state of the switch, activated or not) Therefore the process of building an Entity is non-trivial. I rely on a Component factory to create partial information from the Entity json files, add the runtime data, and finally assemble everything into the final Entity. TypeScript makes it very easy, but still it's a bit of work. Also even though I use .json files, I do "parse" my Entity definitions, mostly to ensure my Components are well-formed. The coupling with Phaser is done via a "SpriteEntity" wrapper ; basically an object that combines both framework. This justifies why simple data like "position" are Components as well, as the logic is non-intuitive - for example when the player steps onto a teleporter, my framework tell Phaser what to do (ECS -> Phaser), but after a collision, Phaser tells my framework what to do (Phaser -> ECS). So some Components only exist to sync the data and and minimise the coupling between the two frameworks. A couple of json Entity definition to help visualise it all : Here, a base definition for Obstacles ; an Obstacle being an object the player cannot walk through but can remove with specific interactions { "id" : "Obstacle", "base" : [ "FullHitbox", "Resettable", "HealthDrop" ], "components" : [ { "type" : "PositionAttributeComponent" }, { "type" : "CollidedPhysicsComponent", "group" : "Object" }, { "type" : "OverlappedPhysicsComponent", "group" : "Object" }, { "type" : "HealthStatComponent", "health" : 1 } ] } This inherits from "FullHitbox" (defines various physics attributes required for collisions, etc.), "Resettable" (a collection of Components, with logic so that the Entity is not destroyed but disabled and respawned when out-of-screen) and "HealthDrop" (another collection of Components, with logic so that this Entity has a chance to drop pickups when removed). Also some additional Components : groups/messages for collisions/overlaps, position (but no data ! it will come from the level file), etc. And now a "specialisation" of an Obstacle : a Grass Entity, which can be removed by attacking it with a Sword { "id" : "Grass", "base" : [ "Obstacle" ], "components" : [ { "type" : "VulnerabilityStatComponent", "entries" : [ { "prototype" : "SwordUse", "damage" : 1 } ], "invulnerabilityTime" : 0 }, { "type" : "StateDisplayComponent", "texture" : "Obstacles", "animations" : [ { "name" : "Default", "frames" : [ 3 ], "framerate" : 0, "loop" : false } ] } ] } We inherit from everything and only specify what's missing : some data for the display system to know what to show on screen, and some data required by the combat logic to handle damage. We then have to fetch the instance bits from the level file (position, name, etc.) and assemble everything into the final Entity. Finally, we have a Grass object, with a collection of behaviours (physics, reset out-of-screen, drops health, etc.), and the ability to take damage from the combat system when overlapped by a Sword attack. And all of this data-driven ; obviously it means knowing how the logic for Components and Systems work, but it makes it easy to add/remove behaviour, and change bits like redefine messages, balance numbers, etc. Also, given working examples of base entities, designers can easily combine things to achieve the result they want (teleporter + moving monster = moving teleporter, etc.) Same goes for more complex objects, such as Monsters ; they have more animations, they have control components for their inputs/AI, etc. So bigger definitions, but same principle. I might release the code of my ECS framework in the future, but I don't think it's mature enough to be published yet (e.g. I don't have a nice elegant way to sort component initialisation order in case of dependencies, and other functionalities). But I'm happy to help / answer questions for people considering a similar approach. 'Hope that helps.