Search the Community
Showing results for tags 'patterns'.
-
I've just been making it up as I go with pixi, and I wanted a sanity check for my approach to entities. My entities have a lot of functionality and effects, but cause FPS drops when about 100 are on screen. Is that appropriate given how complex they are? Is it most likely caused by one specific thing? Is any of this approach decent? As a basic overview, here's how my Pirate class goes: create a class called Pirate, inherits from DisplayObjectContainer add a main ship sprite, alpha set to 1 add an explosion effect (itself a complicated entity), disabled initially and alpha set to 0 add debris sprites that break apart when the ship is destroyed, alpha set to 0 add a hitpoint bar add matrix+filters for a mouse over effect when player targets the pirate check a 'state' variable once per frame, to see when pirate has died once per frame, run the appropriate logic for the state the pirate is in (alive: do nothing, dead: play explosion effect, etc) So to summarize, entities are DisplayObjectContainers containing a bunch of art assets, most of which are invisible at any given point in time. A state variable is monitored by the client, and used to decided which art, effects, etc. to show at any given time. The design has been moving more and more to a component-based pattern, as shown here it is still just a hybrid. Oh, and before I forget, the entities in the game are only clientside graphics! All actual logic relating to the ai/movement/etc occurs on the server at 20 fps. The client interpolates all entities at 60 fps for nice smooth movement. I don't think this causes the main performance issue. When profiled, 18% of the total time is spent in WebGLRenderer.render, and 1.5% in the interpolation. Here's an example of how I create my jellyfish pirate ship. No need to read the code too thoroughly, it's all just a rough outline. There are sounds (howler.js) and object pooling, but I've cut most of that stuff out for now. Here's a very short video of what it looks like: https://www.youtube.com/watch?v=t3udYwZOO50 function Pirate() { PIXI.DisplayObjectContainer.call(this) // for clientside prediction of collisions this.collider = new CircleCollider(this.x, this.y, 15) // shows a medium explosion when destroyed this.explosionEffect = new ExplosionEffect(2) this.addChild(this.explosionEffect) // anything that moves/rotates with the ship goes in shipContainer this.shipContainer = new PIXI.DisplayObjectContainer() // the art for the ship when alive and pristine this.ship = new PIXI.Sprite(PIXI.Texture.fromFrame('jellyfish-spaceship.png')) //this.ship.tint = 0x8888ff this.ship.anchor.x = this.ship.anchor.y = 0.5 // broken up pieces of the ship // these sprites all carefully line up to create a whole ship this.debris = [] this.debris.push( new PIXI.Sprite(PIXI.Texture.fromFrame('jellyfish-debris0.png'))) this.debris.push( new PIXI.Sprite(PIXI.Texture.fromFrame('jellyfish-debris1.png'))) this.debris.push( new PIXI.Sprite(PIXI.Texture.fromFrame('jellyfish-debris2.png'))) this.debris.push( new PIXI.Sprite(PIXI.Texture.fromFrame('jellyfish-debris3.png'))) // initialize the debris with an alpha of 0 for (var i = 0; i < this.debris.length; i++) { var debris = this.debris[i] this.shipContainer.addChild(debris) debris.alpha = 0 debris.anchor.x = debris.anchor.y = 0.5 } this.hpBar = new HitpointBar() /* // debug, most recent server position w/o entity interp this.serverPosition = new PIXI.Graphics() this.serverPosition.lineStyle(2, 0xff0000, 1) this.serverPosition.drawCircle(0, 0, 15) */ this.shipContainer.addChild(this.ship) this.addChild(this.shipContainer) // the hp bar goes outside of shipContainer, so that it does not rotate this.addChild(this.hpBar) //this.addChild(this.serverPosition) this._shipRot = null this.interactive = true // used for mouse over highlight effects var colorMatrix = [ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 ]; var filter = new PIXI.ColorMatrixFilter(); filter.matrix = colorMatrix; // skipped code: mouse over effects that create a highlight via color matrix // skipped code: events fired that cause gui to change cursor}Pirate.prototype = Object.create(PIXI.DisplayObjectContainer.prototype)Pirate.protoype.constructor = PirateHere's where I hackishly check for a state change, and begin the death animation effects: Object.defineProperty(Pirate.prototype, 'state', { get: function() { return this._state }, set: function(value) { // Spawn to Alive if (this._state === EntityState.Spawn && value === EntityState.Alive) { // no spawn effect for this entity } // Alive to Dead if (this._state === EntityState.Alive && value === EntityState.Dead) { // hide the pristine ship, show explosion this.ship.alpha = 0 this.explosionEffect.alpha = 1 this.explosionEffect.begin() // show the debris and break the ship apart for (var i = 0; i < this.debris.length; i++) { var debris = this.debris[i] debris.alpha = 1.0 // vx, vy represent velocity debris.vx = MathEx.random(-15, 15) debris.vy = MathEx.random(-15, 15) debris.rotVelocity = MathEx.random(-5, 5) } } this._state = value }})I'll note that the above code is a getter/setter with side effects, which I've been told is bad form. I intend to move an identical check into update() and then abstract it away into a base entity class. Then when I do make a concrete class, it might have the same logic in sections like onSpawn, onDeath, etc. And then here is the somewhat messy update() function that runs once per frame: Pirate.prototype.update = function(delta) { // update HP bar //TODO: encapsulate the hp bar so we can call hpBar.update(delta) and be done // the hp bar effect is created by growing the empty part this.hpBar.empty.scale.x = -(this.maxHullHp - this.hullHp) / this.maxHullHp // logic if dying if (this.state === EntityState.Dead) { this.explosionEffect.update(delta) // debris moves slowly apart and spins, fades to nothing slowly for (var i = 0; i < this.debris.length; i++) { var debris = this.debris[i] debris.x += debris.vx * delta * 0.1 debris.y += debris.vy * delta * 0.1 debris.rotation += debris.rotVelocity * delta * 0.1 debris.alpha -= 0.35 * delta } // fade out the hp bar this.hpBar.alpha -= 0.35 * delta } // this ship doesn't have a particular animation that goes with it, but // here is approximately how the animation code would go if it did /* if (Date.now() - this.lastFrameTimestamp > this.animationFrameDelay) { this.frameIndex++ this.ship.gotoAndStop(this.frameIndex) this.lastFrameTimestamp = Date.now() if (this.frameIndex > this.totalFrameCount) { this.frameIndex = 0 } } */ // skipped: call to this.finalize() which marks this entity for return to // the object pool}So basically if the entityState is dead, the explosion and debris spreading apart gets to play. Other entities in my game have more significant logic for other states such as spawning effects or animations while alive. Thoughts?? Suggestions? Thanks for reading
- 2 replies
-
- DisplayObjectContainer
- pixi.js
-
(and 2 more)
Tagged with:
-
Hi! This is a question i have been asking myself for a while: What framework are you guys using in combination with a library like Pixi to create games? Do you only use Pixi, do you use Pixi + angularJS or Pixi + some very tiny MVC framework? Why i ask this is because every game has different screens. for example, a title screen and a main game screen. then there can be a 'how to play' screen, highscores, etc. etc. I am currently looking into AngularJS (mostly because i want to have an excuse to finally start learning it) scaffolded with Yeoman. Is there maybe even a Pixi generator i am not aware of? that would be awesome. Thanks for any advice.
-
As someone whose main job is a web dev using jQuery I'm struggling to decide on the best approach to structuring my code now I'm onto states . I appreciate Richard not forcing you to use any particular method but I'd really appreciate being told what method to use right (best practice). I've seen 2 major ways of creating states: 1. In the Examples Repo: Rox.MainMenu = function (game) { this.music = null; this.playButton = null;};// Use of "prototype" indicates "prototype pattern"?Rox.MainMenu.prototype = { create: function () { this.add.image(390, 360, 'photonstorm'); this.input.onDown.addOnce(this.startGame, this); }, update: function () { }, startGame: function (pointer) { this.state.start('Game'); }};2. In LessMilks Flappy Bird Tutorial: // "Object literal notation"?var menu_state = { create: function() { var space_key = this.game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR); space_key.onDown.add(this.start, this); var style = { font: "30px Arial", fill: "#ffffff" }; var x = game.world.width/2, y = game.world.height/2; var text = this.game.add.text(x, y-50, "Press space to start", style); text.anchor.setTo(0.5, 0.5); if (score > 0) { var score_label = this.game.add.text(x, y+50, "score: " + score, style); score_label.anchor.setTo(0.5, 0.5); } }, start: function() { this.game.state.start('play'); }}My ultimate question (without starting a 'religious' war) is: Which of these is best practice way of structuring a game with multiple states like this? Secondly - what are the relative advantages/disadvantages to using either of these methods? Really hoping you can help - I've been reading "Learning JavaScript Design Patterns" by Addy Osmani as well as checking SO to get some insight but the book is just confusing me with even more JS possible patterns so I'm looking to you guys for some prodding in the right direction.
- 6 replies
-
- javascript
- patterns
-
(and 1 more)
Tagged with: