• Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by jamespierce

  1. Nice, I really like it! The puzzles are clever and the art style is beautiful! Sometimes I wish I could speed up the game a bit, to rotate & fall faster, and proceed quicker in the level
  2. I love the polish in this game! And actually getting 3 stars can be challenging especially if the RNG (next bubble to shoot) is against you. But overall I just have to repeat again how insanely polished this is from the menu to the level intro animations and sound effects, just everything! Very inspiring to see this 😮
  3. Game Link: Vocab RPG Vocab RPG is an Online RPG about catching Monsters & collecting Vocabulary Cards! Features: Open world with unique zones to explore MMO: Online multiplayer Monsters: Hunt, battle, and catch many unique monsters! Crafting: Collect different resources and use them to craft items & consumables Language Learning: Unlock vocabulary cards! Currently 4 vocabulary languages to choose from: Chinese, German, Japanese, Russian Overview: In Vocab RPG, you have all the elements of a monster-focused RPG: Hunting, fighting, catching, levelling, crafting, etc. But for every action that you take in the game, it will show you a vocabulary card! As a consequence, the more words you know, the stronger you also become in the game. The game starts very slowly with only 3 words unlocked. But as you progress in the game, you can unlock more cards and expand your vocabulary - at your own pace. Difficulties: To take into account different learning preferences, you can pick your challenge by choosing from 4 difficulty settings: - Normal: Wrong answers reduce your monster's attack or consumables (such as potions) by 25%. - Casual: Even if you answer wrong, you will attack and operate at 100% effectiveness. In other words, you see the cards but there is no consequence for answering wrong. - Hardcore: When you answer wrong, your monster's attack will fail! So answering wrong means 0 damage dealt. - Off: I also want people to enjoy this game, even when they are not really in the mood for studying vocabulary cards right now.... select 'Off' and you will not see any vocabulary cards in the game! Platform: Thanks to the power of Phaser 3, you can play this game on any device in your browser. No installation required. The game is mobile optimized, so whether you play on your laptop or phone / tablet, is only a matter of your preference. Game Link: If you are interested in trying the game, you can jump right into it: Vocab RPG Feedback: Any feedback is much appreciated! We also have a Discord server for the game where players are exchanging ideas, reporting bugs, and giving feedback: Vocab RPG Discord Credits: The game uses a lot of CC0 assets (like the monster sprites in this post) from various artists. I keep a list of all used assets here (which is also accessible from directly inside the game): Credits List
  4. 99.9% I build all UI inside the canvas using Phaser Objects (images, sprites, graphics, tweens, etc.).
  5. For Halloween, I added two new unlockable cards to the game! Any cardpack that you receive from levelling up can now contain these two new cards. Game Link: Pixel Memory
  6. The graphics object also has origin at 0,0. Moreover, graphics objects cannot have a different origin than 0,0. Sorry for sidetracking a bit but this is related info about graphics objects, especially if you are dealing with origins: When you add a graphics object to your scene, make sure you set the x,y coordinates. Else it will default to 0,0 and you might be confused why a graphics object in the center of your screen has its coords set to 0,0. Link to doc: https://photonstorm.github.io/phaser3-docs/global.html#GraphicsOptions If you want to detect input on a graphics object, you have to use a geometry object to manually set the input area. Link to doc: https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Graphics.html#setInteractive__anchor You're right, the doc says it defaults to 0.5. I guess this needs to be updated in the doc. I think there is a place to submit change requests to the doc somewhere but I couldn't find it myself right now.
  7. Check out the tutorial series by the man who helped develop the tilemap system in Phaser 3, it's very good. In the second part of the series he is using a platformer as an example: Part 2 https://itnext.io/modular-game-worlds-in-phaser-3-tilemaps-2-dynamic-platformer-3d68e73d494a I still think you should go through the whole series, though!
  8. @blackhawx Okay I just kept typing and my post was getting a bit out of hand. So I decided to just write it out as a post on my dev blog here: How to Re-Use Phaser 3 Animations for Different Sprite Sheets I hope this was clear and useful! Feel free to "like" the post if it was good or leave feedback how I can improve it. Thanks again for helping me understand this process!
  9. Yes of course! I will post here the code snippet as soon as I've implemented it. I've just flown to Canada last night for a family visit for 2 weeks. So I don't know right now when I'll sit down and code again. But when it's done I'll post it here.
  10. This is even cleaner! No need for helper functions. I still don't use the setData() methods enough in my Phaser 3 projects. Thanks!
  11. Okay so that makes my "workaround" solution above terribly bad because animations are created when the object (npc with a sprite) is created! I'll go back to the way I had it before: Simple helper methods where I provide a string to return the animation-key for the corresponding sprite sheet. I apologize for my naivety in this topic but I'm happy I asked and got all this new information now. I know now the desired approach was unnecessarily "organized" at the cost of being terribly ineffective. Maybe I can extend the Animations object with my helper methods to provide a sprite key and animations key, and it will then play the right animation for that sprite sheet, i.e. 'spr1-walk', 'sp2-walk' etc. And then I'll load all animations from a JSON file! From everything I've understood now, I think this would be a proper approach to Phaser 3.
  12. I have that too xD Sometimes I get lost just optimizing my code or "beautify-ing" my code, when all I wanted to do initially was fix a bug... I know very little about the works behind animation, nor what exactly needs a lot of processing power. I should really start educating myself on such topics. Thanks for pointing this out, at least now I have some good keywords that I can google and research.
  13. I knew there was something to it that was beyond my knowledge! Thank you so much for giving this background information, I really appreciate it. I had no clue that it is actually advantageous to the performance. Since I will be adding tons of sprite sheets, I will really benefit from the way Phaser 3 does it. I will stick with it. Thanks again!
  14. In that case you can use the standard keyboard inputs but don't allow diagonal movement. Then on top of it, you only allow changing directions when it perfectly matches the grid, such as (same concept for y-coordinates): function allowChangeDirection() { if(player.x % tile_size === 0) { return true; } else { return false; } } Now the problem with this will be that if your tile_size is not divisible for the player's speed, then the check will never return true. To fix this, you can increase the range that you check by the speed / velocity value: function allowChangeDirection() { if(player.x % tile_size <= player.speed) { return true; } else { return false; } } Then when you finally change direction on the grid, round the player's coordinates to fit perfectly onto the grid. Else over time your player might end up a bit off the grid. if(allowChangeDirection()) { player.setPos( Math.round(player.x / tile_size), Math.round(player.y / tile_size) ); } This is just a general approach but you can play around with it and tweak the values for the checks & player coords which feel best for your particular game.
  15. Brilliant approach! You're right, it could be expanded or we could create a custom plugin to make it work. That's what Phaser 3 was intended for in the first place! I didn't even think about it. Thanks for the link to the other topic. I didn't mean to create a duplicate. I searched the forum before posting but did not come across it. In the other topic you've linked, @rich said the above thing. I am highly confused now because in v3 it appears to be exactly the opposite: You absolutely must duplicate the animation frames if they are targeting a different sprite sheet! @jest Do you know what he meant? How do you re-use global animation data in v3?
  16. @blackhawx Thank you for your reply! Unfortunately, your solution doesn't solve the problem. That's just the manual approach, which I was doing before myself: Create the animation for every sprite sheet. However, I'm adding more and more sprites (skins) and the list of animations will grow to a huge list. It doesn't make any sense because the frame sequence is exactly the same for every sprite sheet. So why should we fill up the AnimationsManager with so many animations, when 1 would be applicable to all of them? That's what I'm trying to solve. Unfortunately, as long as the animation is bound to the sprite sheet, there is no way to re-use it. So yeah, if that's really the case then your solution above is probably the best one. But if you have 100 skins in the game for example, that means adding 100 animations... Since in Phaser 2 it was possible (as a matter of fact, it was the default behavior of animations), I am sure it is also possible in Phaser 3. I just don't know how and studying the lab examples & documentation is not helping me anymore >.<
  17. EDIT: See some comments later below why this workaround is not good! If you can, create all your anims at the start of the game. (Here I wanted to create anims when the object is instantiated, which could be at the start but also anytime during the game.) ------------------------------------------------------------------------------------------------------- For now I found a work-around that works like this: Instantiate object that has a sprite & name. Sprite is random for every instance, but they all share the same walk animation frames: [0, 1, 2, 3 ] Upon instantiating, each object creates it's own animation... said animation is bound to his spritesheet as texture I created a helper function to get the animation frames by key However, I have a hard time seeing that it is really the goal to create unique animations like this, even if they share the exact same sequence of frames. In Phaser 2, animations could be re-used for any sprite sheet, as long as the frame sequence was identical (such as my example here). I'm sure there is a way in Phaser 3 but I just can't figure it out. Anyways, for now this is my workaround code below. But if anyone of you knows how to do this properly, any insight would be much appreciated! let getAnimFramesByKey = function(key) { 'use strict'; let frames = []; switch(key) { case 'walk': frames = [ 0, 1, 2, 3 ] break; case 'run': frames = [ 4, 5, 6, 7 ] break; // etc. } return frames; }; // Inside the object with a sprite and name: // this.scene is just a reference to the Phaser Scene inside which it was instantiated // Create the object // this.spr = Phaser Sprite Object // this.NAME = a unique name given to this object // this.spr_id = the id of the spritesheet that was loaded into the game, i.e. 'spr1', 'spr2' etc. ObjectName.prototype.create = function() { // Phaser Sprite Object let key = 'spr' + this.spr_id; this.spr = this.scene.add.sprite(this.x, this.y, key); // Animations... // ...check if this animation was already created if(this.scene.anims.anims.entries['walk-' + this.NAME]) { return; } // ...create the animation, bound to the object's sprite texture this.scene.anims.create({ key : 'walk-' + this.NAME, frames : this.scene.anims.generateFrameNumbers('spr' + this.spr_id, { frames: getAnimFramesByKey('walk') }), repeat : -1, frameRate : 9 }); }; ObjectName.prototype.triggerAnim = function(key) { // Play the animation, which is bound to this sprite sheet switch(key) { case 'walk': this.spr.play('walk-' + this.NAME); break; default: // idle this.spr.anims.stop(); this.spr.setFrame(0); } };
  18. If you mean "click to move" in a grid-based world, I've written a tutorial about how to do that using the A* algorithm: A* Pathfinding in JavaScript for HTML5 Games (With Phaser 3)
  19. EDIT: Click here to jump directly to my dev blog explaining my current solution. Keep reading if you want to get some valuable background information to why Phaser 3 anims work the way they do now, and why it's better. ---------------------------------------------------------------------------------------------------------------------- I have different sprite sheets that have the same sequence in the exact same frame numbers, such as: walk = [0, 1, 2, 3] I have checked every example in the Phaser 3 labs and all of them bind the animation to the sprite sheet. So when I would do .play('walk') it always takes the textures of the sprite sheet the animation was bound to. this.anims.create({ key : 'walk', frames : this.anims.generateFrameNumbers('spritesheet1', { frames: [ 0, 1, 2, 3 ] }), repeat : -1, frameRate : 9 }); How can I take the above animation and re-use it on any sprite sheet where the frames [ 0, 1, 2, 3 ] apply to walking?
  20. I apologize in advance if this should be obvious... Regarding destroying / removing cameras that I don't need anymore, I came across these two descriptions in the documentation that sound a bit contradicting to me: Camera.destroy(): CameraManager.remove(camera): So for destroy() it says that I should use CameraManager.remove(). However for remove() it says that I need to call Camera.destroy() to clear all references. @rich What's the "clean" way to do it? Call remove() first and then destroy() after? Or just one of the two?
  21. @VincentB If you want to center text inside an image, sprite, or graphics, you have to do this: // Create image with this.add.image() or this.add.sprite() // Create text with this.add.text(); text.setOrigin(0.5); text.setX(img.getCenter().x); text.setY(img.getCenter().y); But there is a problem with your example in particular: The center-point of the image is not where you want your text to be because of the 'spike' going from the rectangle to the talking NPC. So in this case, what you need to do is subtract the height of the 'spike' from the y-position. (If that 'spike' was sticking out in another direction, you'd need to adjust that coordinate accordingly.) Anyways, let's stick with your example: let offset = 21; // Height of the 'spike' going out of your speech bubble text.setX(img.getCenter().x); text.setY(img.getCenter().y - offset);
  22. @rado9408 I've posted a code example in another thread asking the same question. If you're still struggling, you can check it out here: