gregkarber

Members
  • Content Count

    27
  • Joined

  • Last visited

Everything posted by gregkarber

  1. Hello, all! I am a writer/director living in Los Angeles. A couple years ago, I started working on a simple procedurally-generated lettuce platformer in Phaser. You play as a head of lettuce trying to climb a mountain to reunite with your tortoise love. Since then, I have repeatedly been sidetracked by other projects and am now returning to it with the hopes of releasing it in the next month or so. You can play a demo of the game at http://gregkarber.com/lettuceclimb (but please do not share). As you can see, for a game that is this simple (about ~2500 lines of code), I have persistent problems with framerate. I believe that I could discern the solution to this problem, but it would take me a lot of time and (frankly) I would rather spend that time working on other projects. I am looking to hire someone to help me optimize this code to improve the framerate. Please feel free to examine the source code in the above link and send me your rates and timeframe, or introduce yourself, or do whatever the next step is. I have never hired a programmer before, so you'll probably have more experience with how to go about this than I do. I would prefer to hire someone who enjoys the game and who could be a collaborator in the future. I have a couple mostly-completed games, and I would be interested in hiring someone for those, too, depending on how well we work together. (All of those would be paid, as well!) Thank you very much!
  2. I am trying to fix a problem with a circular body falling between rectangular bodies, so I was debugging it, and I noticed that my main sprite body looks like below (I have made the sprite itself invisible so that you can see the debug body). It seems that the radius in that image shows the actual boundary of the body, not the circle. Previously, when I've done this, the radius touches the edge of the circle. So, my question is, what is going on in this picture? What do the circle and the radius represent? I know this is a pretty fundamental thing, but I'm lost, so -- going forward -- is there any place/book/text I should use to figure out basic things like this in the future? Thank you very much for any help!
  3. gregkarber

    Sprite Falling Through P2 Sprites

    Through more testing, I've come to realize that the main lettuce sprite doesn't fall through the ground sprites, it falls between them. Is there anyway to avoid that?
  4. gregkarber

    Sprite Falling Through P2 Sprites

    I'm working on a procedurally-generated mountain climbing game where you play as a head of lettuce. You can play the working demo here. I have a bunch of work to do regarding streamlining the code and the gameplay, but I can't seem to resolve a problem. When the head of lettuce falls from a substantial height, he falls through the black rectangle sprites I use for the ground. This means it falls through platforms. In addition, since the ground is only one physics-enabled sprite deep, if he falls through that, he falls through the world and the game is over. I feel like perhaps tweaking the Contact Materials might help solve this problem, but I can't find sufficient docs to really understand. Can anybody help me with this? I have copy-pasted some of the relevant passages of code below, but the full text is available as an attached text file. (You can also view it here.) Any help (even just directions to pursue) would be enormously helpful! Thank you very much. this.lettuce.body.setMaterial(this.spriteMaterial); this.spriteMaterial = game.physics.p2.createMaterial('spriteMaterial', this.lettuce.body); this.worldMaterial = game.physics.p2.createMaterial('worldMaterial'); this.platformMaterial = game.physics.p2.createMaterial('platformMaterial'); this.smoothMaterial = game.physics.p2.createMaterial('smoothMaterial'); this.smootherMaterial = game.physics.p2.createMaterial('smootherMaterial'); this.lettuce.body.setMaterial(this.spriteMaterial); game.physics.p2.setWorldMaterial(this.worldMaterial, true, true, true, true); var contactMaterial = game.physics.p2.createContactMaterial(this.spriteMaterial, this.platformMaterial); contactMaterial.friction = 7; contactMaterial.restitution = .1; contactMaterial.stiffness = 1e7; contactMaterial.relaxation = 7; contactMaterial.frictionStiffness = 1e7; contactMaterial.frictionRelaxation = 3; contactMaterial.surfaceVelocity = 0; var contactMaterial2 = game.physics.p2.createContactMaterial(this.smoothMaterial, this.platformMaterial); contactMaterial2.friction = 0; contactMaterial2.restitution = 0; contactMaterial2.stiffness = 1e7; contactMaterial2.relaxation = 10; contactMaterial2.frictionStiffness = 1e7; contactMaterial2.frictionRelaxation = 3; contactMaterial2.surfaceVelocity = 0; var contactMaterial3 = game.physics.p2.createContactMaterial(this.smootherMaterial, this.platformMaterial); contactMaterial3.friction = 0; contactMaterial3.restitution = 0; contactMaterial3.stiffness = 0; contactMaterial3.relaxation = 0; contactMaterial3.frictionStiffness = 0; contactMaterial3.frictionRelaxation = 0; contactMaterial3.surfaceVelocity = 0; And the update function, among other things, calls this: friction_manager: function() { // so that ceilings are smooth if (this.checkIfCeiling()) { this.lettuce.body.setMaterial(this.smoothMaterial); } else this.lettuce.body.setMaterial(this.spriteMaterial); }, And this is the function that actually places and sets the platforms: place_block: function(x,y, bodiful) { this.visiblesprites.push((Math.round(x) + ',' + Math.round(y))); x = x*TILE; y = y*TILE; var ground = this.platforms.getFirstDead(); ground.reset(x,y); if (bodiful) { game.physics.p2.enable(ground); ground.body.static = true; ground.body.setMaterial(this.platformMaterial); } else { ground.anchor.setTo(0.5, 0.5); } }, I also wrote this to limit the speed of the lettuce falling, in the hopes that that would fix it, but it didn't, really: if (this.lettuce.body.velocity.y > 2000) this.lettuce.body.velocity.y = 2000; Anyway, if anyone can offer any help, that would be hugely appreciated! main2.txt
  5. gregkarber

    Game lags over time: help with efficiency!

    Oh man, the emitter thing. I'm sure that's it. Thank you very much! These were all great ideas, and thank you so much for the kind comments on the game itself. That's wonderful.
  6. I made a game called The Space Beyond and it starts out really fluid and smooth but if you play for a couple minutes the framerate drops and it gets really laggy. I'm already (1) killing and reseting the asteroids from a pool, (2) killing any asteroids that get too far away, and (3) there's never more than like 30 sprites at any given time. But still it goes so slow. I can't figure out why that is. I'm sure there's something I'm missing, but I am an amateur coder and don't really know what I'm doing. I have copy-pasted the complete code for the game below. If anybody could figure this out, I would be very very very grateful. Thank you very much. var displayGroup;var sprite;var shapeSprite;var cursors;var fuelRatio = {"value":1};var fuelBar;var beenhere = 0;var shipCollisionGroup;var asteroidCollisionGroup;var asteroid;var spacerocks;var threshold = {"x": 0, "y":0};var loss = false;var reset = {"x":0, "y":0};var textdisplay;var fuelLoc = {"x":0, "y":0};var dial;var fuelPodSprite;var refilling = false;var asteroidCircle;var asteroidGroup;var fuelPodCircle;var storyArray;var storyBoard;var score = 0;var newMessage = "";var returnToNormal = true;var music;var game = new Phaser.Game(700, 500, Phaser.CANVAS, 'game_div', this);var game_state = {};game_state.preload = function() { };game_state.preload.prototype = {preload: function() { game.world.setBounds(0, 0, 800*100, 600*100); game.stage.backgroundColor = "#000000"; game.load.image('title', 'title.png');},create: function () { game.state.start('load'); }}game_state.load = function() { };game_state.load.prototype = {preload: function() { this.titleSprite = game.add.sprite(53, 170, 'title'); this.game.load.setPreloadSprite(this.titleSprite); this.game.load.image('ship', 'ship.png'); this.game.load.audio('music', ['LOVELOST.ogg', 'LOVELOST.mp3']); this.game.load.image('square', 'square.png'); this.game.load.image('dial', 'dial.png');},create: function () { music = game.add.audio('music'); music.play(); game.state.start('menu'); }}game_state.menu = function() { };game_state.menu.prototype = { preload: function() { }, create: function() { this.game.input.keyboard.callbackContext = this; this.storyStyle = { font: "30px Courier", fill: "#FFFFFF" }; this.loadinstructions = game.add.text(155, 300, "Press any key to play", this.storyStyle); game.input.keyboard.addKeyCapture(Phaser.Keyboard.SPACEBAR); this.loadinstructions.alpha = 0; game.add.tween(this.loadinstructions).to({"alpha": 1}, 1500, Phaser.Easing.Linear.None, true); this.game.input.keyboard.onDownCallback = this.fadeOut; this.titleSprite = game.add.sprite(53, 170, 'title'); }, fadeOut: function() { this.game.input.keyboard.onDownCallback = null; this.fade = game.add.tween(this.game.world).to({"alpha": 0}, 500, Phaser.Easing.Linear.None, true); this.fade.onComplete.add(this.runGame); }, runGame: function() { game.state.start('main'); }}game_state.main = function() { };game_state.main.prototype = {preload: function() { }, create: function() { this.justonce = 0; game.physics.startSystem(Phaser.Physics.P2JS); //spacerocks = game.add.group(); displayGroup = game.add.group(); game.physics.p2.restitution = .01; //game.physics.p2.applyDamping = true; shipCollisionGroup = game.physics.p2.createCollisionGroup(); asteroidCollisionGroup = game.physics.p2.createCollisionGroup(); fuelPodCollisionGroup = game.physics.p2.createCollisionGroup(); beenhere = 0; // This will run in Canvas mode, so let's gain a little speed and display game.renderer.clearBeforeRender = true; game.renderer.roundPixels = true; fuelBar = game.add.graphics(0, 0); fuelBar.fixedToCamera = true; displayGroup.add(fuelBar); // Our player ship this.sprite = this.game.add.sprite(400*100, 300*100, 'ship'); this.sprite.anchor.set(0.5); this.sprite.angle = 90; this.sprite.scale.x = .5; this.sprite.scale.y = .5; game.physics.enable(this.sprite, Phaser.Physics.P2JS); this.sprite.body.clearShapes(); this.sprite.body.addPolygon({}, [25, 15, 12, 50, 38, 50]); this.sprite.body.setCollisionGroup(shipCollisionGroup); this.sprite.body.damping = .1; this.sprite.body.angularDamping = .99; this.sprite.anchor.setTo(0.5,0.65); this.sprite.name = 'sprite'; //sprite.body.debug = true; this.sprite.body.onBeginContact.add(this.gotHit, this); this.sprite.body.collides(asteroidCollisionGroup); //sprite.body.collides(fuelPodCollisionGroup); threshold.x = this.sprite.x; threshold.y = this.sprite.y; cursors = game.input.keyboard.createCursorKeys(); spacebar = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR); game.input.keyboard.addKeyCapture(Phaser.Keyboard.SPACEBAR); game.camera.follow(this.sprite); this.circleCreate(); this.asteroidGen(); fuelPodCircle = game.add.graphics(0, 0); this.fuelPod(this.sprite.x+15, this.sprite.y+15); this.fuelArrowSpawn(); this.fuelRemaining(); this.storyInit(); this.boardInit(); game.physics.p2.setPostBroadphaseCallback(this.checkOverlap, this); game.add.tween(game.world).to({"alpha": 1}, 500, Phaser.Easing.Linear.None, true);},checkOverlap: function(body1, body2) { if ((body1.sprite.name === 'sprite' && body2.sprite.name === 'fuelPodSprite') || (body2.sprite.name === 'fuelPodSprite' && body1.sprite.name === 'sprite')){ this.fuelGet(); //whatever you need on overlap return false; } return true;},asteroidGen: function(dir) { console.log("dir: " + dir); var xer = 0; var yer = 0; // WRITE CODE TO MAP AN ARRAY AND THEN PLACE THEM IN THE ARRAY! var doubleCheck = []; var newPoint = ""; for (var b = 0; b < 10; b++) { if (dir == "right") { xer = this.sprite.x + 400 + Math.floor(Math.random() * 800/100)*100; yer = this.sprite.y - 300 + Math.floor(Math.random() * 1200/100)*100; } else if (dir == "down") { xer = this.sprite.x - 1200 + Math.floor( Math.random() * 1600/100)*100; yer = this.sprite.y + 300 + Math.floor(Math.random() * 600/100)*100; } else if (dir == "left") { xer = this.sprite.x - 400 - Math.floor(Math.random() * 800/100)*100; yer = this.sprite.y - 900 + Math.floor(Math.random() * 1200/100)*100; } else if (dir == "up") { xer = this.sprite.x - 400 + Math.floor(Math.random() * 1600/100)*100; yer = this.sprite.y - 300 - Math.floor(Math.random() * 600/100)*100; } else { xer = this.sprite.x - 800 + Math.floor(Math.random() * 1600/100)*100; yer = this.sprite.y - 600 + Math.floor(Math.random() * 1200/100)*100; newPoint = xer + "," + yer; if ((doubleCheck.indexOf(newPoint) == -1) && ( (Math.abs(xer - this.sprite.x) > 50) && (Math.abs(yer - this.sprite.y) > 50) )) { this.asteroids(xer, yer); doubleCheck.push(newPoint); } xer = this.sprite.x - 800 + Math.floor(Math.random() * 1600/100)*100; yer = this.sprite.y - 600 + Math.floor(Math.random() * 1200/100)*100; } newPoint = xer + "," + yer; if ((doubleCheck.indexOf(newPoint) == -1) && ( (Math.abs(xer - this.sprite.x) > 50) && (Math.abs(yer - this.sprite.y) > 50) )) { this.asteroids(xer, yer); doubleCheck.push(newPoint); } } console.log("actually placed:" + doubleCheck.length); //asteroidGroup.forEachAlive(constrainVelocity, this, 25);},toRadians:function (angle) { return angle / (180 / Math.PI);},explode: function() { var explosion = game.add.emitter(this.sprite.x, this.sprite.y); explosion.makeParticles('square'); explosion.setAlpha(1, 0, 5000, Phaser.Easing.Quintic.None); explosion.setScale(.2, 1, .2, 1, 0); explosion.setRotation(500,1000); explosionarea = new Phaser.Rectangle(-1, -1, 2, 2); explosion.gravity = 0; explosion.area = explosionarea; explosion.start(true, 5000, null, 20); explosion.update();},fuelGet: function() { console.log("fuelPodSprite.x: " + fuelPodSprite.x); this.storyTeller(); if (this.instruct) this.instruct.text = ""; score++; var distance = this.scoreCalc(); var moveX = Math.random() * distance; var moveY = Math.sqrt(Math.pow(distance, 2) - Math.pow(moveX, 2)); if (Math.floor(Math.random() * 2) == 0) moveY = 0 - moveY; returnToNormal = false; fuelPodSprite.body.x = fuelPodSprite.body.x + moveX; fuelPodSprite.body.y = fuelPodSprite.body.y + moveY; fuelPodSprite.body.velocity.x = 0; fuelPodSprite.body.velocity.y = 0; fuelPodSprite.angle = 0; displayGroup.bringToTop(fuelBar); game.add.tween(fuelRatio).to({"value":1}, 500, Phaser.Easing.Linear.None, true); var rotateTween = game.add.tween(dial).to({"rotation":Math.atan2(fuelLoc.y - this.sprite.y, fuelLoc.x - this.sprite.x)}, 250, Phaser.Easing.Linear.None, true); rotateTween.onComplete.add(this.dialMan); refilling = true; fuelLoc.x = fuelPodSprite.body.x; fuelLoc.y = fuelPodSprite.body.y; console.log("fuelPodSprite.x: " + fuelPodSprite.x); },dialMan: function() { returnToNormal = true;},scoreCalc: function() { if (score == 1) return 250; else if (score == 2) return 500; else if (score == 3) return 750; else if (score == 4) return 1000; else if (score == 5) return 1250; else if (score == 6) return 1500; else if (score == 7) return 1750; else if (score == 8) return 2000; else if (score == 9) return 2250; else return 2500;},boardInit: function() { this.storyStyle = { font: "25px Courier", fill: "#FFFFFF" }; storyBoard = game.add.text(45, 35, "", this.storyStyle); storyBoard.setShadow(3, 3, '#000000', 5); storyBoard.lineheight = 40; storyBoard.fixedToCamera = true;},storyInit: function() { storyArray = [ "They left you behind", "So did he", "Now you’re lost", "In the space beyond", "Your memories and your dreams", "In your dreams, he still smiles,", "But your future is your past", "Lost forever", "Even if you made it home,", "It’s just another empty rock", "In an empty space.", "Some dreams fade in the light.", "But if you can make it one more night,", "You’ll make it one more night.", ];},storyTeller: function() { if (storyArray.length > 0) { var newText = storyArray.splice(0,1); console.log(newText[0]); this.newTrans(newText[0]); } else this.newTrans("You'll make it one more night."); },thrustExhaust: function() { var exhaust = game.add.emitter(this.sprite.x, this.sprite.y); exhaust.makeParticles('square'); exhaust.setScale(.2, .3, .2, .3, 0); exhaust.setRotation(500,1000); //console.log("rotations in pi: " + sprite.rotation/3.141592); var theangle = this.toRadians(this.sprite.angle); var xVec = 0 - Math.sin(theangle); var yVec = Math.cos(theangle); exhaust.setAlpha(1, 0, 500, Phaser.Easing.Quadratic.None); exhaust.x = this.sprite.x+xVec*20; exhaust.y = this.sprite.y + yVec*20; exhaustport = new Phaser.Rectangle(-5, -5, 10, 10); exhaust.area = exhaustport; //console.log("Thrust X, Y: " + Math.cos(sprite.rotation) * 300 + "," + Math.sin(sprite.rotation) * 300); var yThrust = yVec * 300 + (this.sprite.body.velocity.y); var xThrust = xVec * 300 + (this.sprite.body.velocity.x); exhaust.setYSpeed(yThrust - 100, yThrust + 100); exhaust.setXSpeed(xThrust - 100, xThrust + 100); exhaust.gravity = 0; exhaust.start(true, 500, null, 25); exhaust.update();},constantGen: function() { //console.log("constantGen"); if ((threshold.x + 400) < this.sprite.x) {this.asteroidGen("right"); threshold.x = this.sprite.x; this.killAsteroids();} if ((threshold.x - 400) > this.sprite.x) {this.asteroidGen("left"); threshold.x = this.sprite.x; this.killAsteroids();} if ((threshold.y + 300) < this.sprite.y) {this.asteroidGen("down"); threshold.y = this.sprite.y; this.killAsteroids();} if ((threshold.y - 300) > this.sprite.y) {this.asteroidGen("up"); threshold.y = this.sprite.y; this.killAsteroids();}},killAsteroids: function() { console.log("asteroid count: " + asteroidGroup.countLiving()); asteroidGroup.forEachAlive(this.destruction, this);},destructionForSure: function(rock) { rock.kill();},destruction: function(rock) { if ((rock.x < (threshold.x - 1000)) || (rock.x > (threshold.x + 1000)) || (rock.y > (threshold.y + 1000)) || (rock.y < (threshold.y - 1000))) { rock.kill(); } else { //this.constrainVelocity(rock, 10); }},constrainVelocity: function(sprite, maxVelocity) { console.log("starting constraint " + maxVelocity); var body = sprite.body var angle, currVelocitySqr, vx, vy; vx = body.data.velocity[0]; vy = body.data.velocity[1]; currVelocitySqr = vx * vx + vy * vy; if (currVelocitySqr > maxVelocity * maxVelocity) { angle = Math.atan2(vy, vx); vx = Math.cos(angle) * maxVelocity; vy = Math.sin(angle) * maxVelocity; body.data.velocity[0] = vx; body.data.velocity[1] = vy; console.log('limited speed to: '+maxVelocity); }},controls: function() { if (cursors.up.isDown) { if (fuelRatio.value > 0) { fuelRatio.value -= .004; this.sprite.body.thrust(200); this.thrustExhaust(); } this.fuelRemaining(); } else { } if (cursors.left.isDown) { this.sprite.body.angularVelocity = -4; } else if (cursors.right.isDown) { this.sprite.body.angularVelocity = 4; } else { }},update: function() { if (loss == false) this.controls(); this.constantGen(); if (spacebar.isDown) { if ((this.lockSpace != true) && (loss == true)) this.reStart(); else if (fuelRatio.value < 0) { this.explode(); this.fail(); this.lockSpace = true; console.log("explode"); } } else if (this.lockSpace == true) {this.lockSpace = false; console.log("unlocking");} if (returnToNormal == true) this.fuelArrow(); if (refilling == true) this.fuelRemaining();},fuelArrowSpawn: function() { dial = game.add.sprite(650, 50, 'dial'); // 750 dial.anchor.set(0.5); dial.angle = -90; dial.scale.x = .5; dial.scale.y = .5; dial.fixedToCamera = true;},fuelArrow: function() { //console.log(Math.atan(fuelLoc.y - sprite.y, fuelLoc.x - sprite.x)); fuelLoc.x = fuelPodSprite.x; fuelLoc.y = fuelPodSprite.y; dial.rotation = Math.atan2(fuelLoc.y - this.sprite.y, fuelLoc.x - this.sprite.x); },fuelPod: function(x, y) { fuelPodCircle = game.add.graphics(0, 0); fuelLoc.x = x; fuelLoc.y = y; fuelPodCircle.beginFill('0xCC9999'); fuelPodCircle.lineStyle(1, 0xCC9999); fuelPodCircle.drawRoundedRect(0, 0, 10, 15, 2); fuelPodSprite = game.add.sprite(x, y); game.physics.p2.enable(fuelPodSprite, false); fuelPodSprite.addChild(fuelPodCircle); fuelPodSprite.body.clearShapes(); fuelPodSprite.anchor.x = .5; fuelPodSprite.anchor.y = .5; fuelPodSprite.body.addCapsule(4, 5, 5, 8, 3.14/2); //fuelPodSprite.body.debug = true; fuelPodSprite.name = 'fuelPodSprite'; fuelPodSprite.body.collides([asteroidCollisionGroup, shipCollisionGroup]); fuelPodSprite.body.setCollisionGroup(fuelPodCollisionGroup); displayGroup.add(fuelPodSprite); },circleCreate: function() { var circleSize = Math.random() * 50 + 60; asteroidCircle = game.add.bitmapData(100, 100, "asteroidBit", true); asteroidCircle.circle(50, 50, 50, "#FFFFFF") asteroidGroup = game.add.group(); asteroidGroup.createMultiple(100, asteroidCircle); },asteroids: function(x, y) { //console.log("asteroid at " + x + "," + y); var circleSize = Math.random() * .5 + .5; //asteroidGroup.forEachAlive(checkOverlap, this, x, y); asteroid = asteroidGroup.getFirstDead(); asteroid.scale.x = circleSize; asteroid.scale.y = circleSize; asteroid.reset(x,y); asteroid.anchor.x = .5; asteroid.anchor.y = .5; console.log("?" + asteroid.body); if (asteroid.body == null) { game.physics.p2.enable(asteroid, false); asteroid.body.clearShapes(); asteroid.body.addCircle(circleSize * 50); asteroid.body.setCollisionGroup(asteroidCollisionGroup); asteroid.body.collides([shipCollisionGroup, asteroidCollisionGroup, fuelPodCollisionGroup]); //asteroid.body.debug = true; asteroid.body.damping = .1; } asteroid.body.velocity.x = Math.random() * 30 - 15; asteroid.body.velocity.y = Math.random() * 30 - 15; //this.spacerocks.add(asteroid); },gotHit: function(body) { if (body.sprite.name != "fuelPodSprite"){ this.explode(); this.fail(); } else this.fuelGet(); },newTrans: function(newWords) { var fadeOut = game.add.tween(storyBoard).to({alpha:0}, 200, Phaser.Easing.Linear.None, true); fadeOut.onComplete.add(this.newBoard); newMessage = newWords;},newBoard: function() { storyBoard.text = newMessage; game.add.tween(storyBoard).to({alpha:1}, 600, Phaser.Easing.Linear.None, true, 500);},fail: function() { reset.x = this.sprite.x; reset.y = this.sprite.y; this.sprite.kill(); var message = this.finalMessage(); this.newTrans(message); this.instruct = game.add.text(45, 65, "Press spacebar to try again.", this.storyStyle); this.instruct.alpha = 0; this.instruct.setShadow(3, 3, '#000000', 5); this.instruct.lineheight = 40; this.instruct.fixedToCamera = true; game.add.tween(this.instruct).to({"alpha": 1}, 500, Phaser.Easing.Linear.None, true, 2000); loss = true; },finalMessage: function() { var closingThoughts = ["Death is the final dream.", "You die with his face on your mind.", "The air explodes from your lungs.", "You are forgotten.", "The inevitable happens."]; if (this.instruct) this.instruct.text = ""; return closingThoughts[Math.floor(Math.random() * closingThoughts.length)];},reStart: function() { this.fade = game.add.tween(this.game.world).to({"alpha": 0}, 1000, Phaser.Easing.Linear.None, true, 100); this.fade.onComplete.add(this.reStart2, this);},reStart2: function() { asteroidGroup.forEachAlive(this.destructionForSure, this); loss = false; score = 0; fuelRatio.value = 1; //this.sprite.reset(reset.x, reset.y); this.storyInit(); storyBoard.text = " "; this.fuelRemaining(); game.state.start('main'); },fuelRemaining: function() { if (fuelRatio.value <= 0) { fuelBar.clear(); if (this.justonce != 1) { this.newTrans("You run out of fuel."); this.instruct = game.add.text(45, 65, "Press spacebar to self-destruct.", this.storyStyle); this.instruct.alpha = 0; this.instruct.setShadow(3, 3, '#000000', 5); this.instruct.lineheight = 40; this.instruct.fixedToCamera = true; game.add.tween(this.instruct).to({"alpha": 1}, 500, Phaser.Easing.Linear.None, true, 2000); this.justonce = 1; this.lockSpace = true; } } else { //console.log(fuelRatio); fuelBar.clear(); fuelBar.beginFill(0xFFFFFF); fuelBar.lineStyle(10, 0xFFFFFF, 1); fuelBar.drawRect(100, 450, 500*fuelRatio.value, 10); // 100, 550, 600 if (fuelRatio.value == 1) refilling = false; }},render: function() {}}game_state.end = function() { };game_state.end.prototype = { preload: function() { }, create: function() { }, update: function() { }}game.state.add('preload', game_state.preload);game.state.add('load', game_state.load); game.state.add('menu', game_state.menu); game.state.add('main', game_state.main);game.state.add('end', game_state.end); game.state.start('preload'); Thank you very much for any assistance that anyone is able to offer. I also hope you enjoy the game if you play it!
  7. gregkarber

    My game works, but I want it to work faster

    I think I implemented your suggestion! It still could run a little faster, though... function circleCreate() { var circleSize = Math.random() * 50 + 60; asteroidCircle = game.add.bitmapData(100, 100, "asteroidBit", true); asteroidCircle.circle(50, 50, 50, "#FFFFFF") asteroidGroup = game.add.group(); asteroidGroup.createMultiple(100, asteroidCircle); }function asteroids(x, y) { //console.log("asteroid at " + x + "," + y); var circleSize = Math.random() * .5 + .5; asteroid = asteroidGroup.getFirstDead(); asteroid.reset(x,y); asteroid.anchor.x = .5; asteroid.anchor.y = .5; asteroid.scale.x = circleSize; asteroid.scale.y = circleSize; game.physics.p2.enable(asteroid, false); asteroid.body.clearShapes(); asteroid.body.addCircle(circleSize * 50); asteroid.body.setCollisionGroup(asteroidCollisionGroup); asteroid.body.collides([shipCollisionGroup, asteroidCollisionGroup]); asteroid.body.debug = true; asteroid.body.velocity.x = Math.random() * 50 - 25; asteroid.body.velocity.y = Math.random() * 50 - 25; this.spacerocks.add(asteroid); }
  8. I'm working on a game called "The Space Between" for a gamejam, and I have a problem with memory efficiency. I'm drawing asteroids as circles and destroying them when I don't need them, but it still starts to lag a bit as the game goes on. How can I make it faster and smoother? Here is a link to the game, and copy-pasted below is the part that deals with asteroid creation and, below that, the entire source code (all 382 lines of it). I don't really know anything about memory allocation, so I'm sure I'm making some pretty elementary errors. (Also, there's no loading screen yet, so give it a minute to pop up!) Thank you very much for any help you can give! Asteroid Creation/Destruction Code: // This function is called in update and constantly checks to see if certain thresholds are passed.// If they are, it generates a rectangular area of asteroids and calls a function to destroy others.function constantGen() { if ((threshold.x + 400) < sprite.x) {asteroidGen("right"); threshold.x = sprite.x; killAsteroids();} if ((threshold.x - 400) > sprite.x) {asteroidGen("left"); threshold.x = sprite.x; killAsteroids();} if ((threshold.y + 300) < sprite.y) {asteroidGen("down"); threshold.y = sprite.y; killAsteroids();} if ((threshold.y - 300) > sprite.y) {asteroidGen("up"); threshold.y = sprite.y; killAsteroids();}}// This is the function that generates asteroids when the ship gets to the edge of an areafunction asteroidGen(dir) { console.log("dir: " + dir); var xer = 0; var yer = 0; for (var b = 0; b < 10; b++) { if (dir == "right") { xer = sprite.x + 400 + Math.random() * 800; yer = sprite.y - 300 + Math.random() * 1200; } else if (dir == "down") { xer = sprite.x - 1200 + Math.random() * 1600; yer = sprite.y + 300 + Math.random() * 600; } else if (dir == "left") { xer = sprite.x - 400 - Math.random() * 800; yer = sprite.y - 900 + Math.random() * 1200; } else if (dir == "up") { xer = sprite.x - 400 + Math.random() * 1600; yer = sprite.y - 300 - Math.random() * 600; } else { xer = sprite.x - 800 + Math.random() * 1600; yer = sprite.y - 600 + Math.random() * 1200; asteroids(xer, yer); xer = sprite.x - 800 + Math.random() * 1600; yer = sprite.y - 600 + Math.random() * 1200; } asteroids(xer, yer); } }// This is the function that sends all of the asteroid sprites to a destruction functionfunction killAsteroids() { console.log("spacerock count: " + spacerocks.length); spacerocks.forEachAlive(destruction, this); console.log("spacerock count after destruction: " + spacerocks.length);}// This function checks to see if asteroids are too far away and destroys themfunction destruction(rock) { //console.log("check for destruction"); if ((rock.x < (threshold.x - 1000)) || (rock.x > (threshold.x + 1000)) || (rock.y > (threshold.y + 1000)) || (rock.y < (threshold.y - 1000))) { rock.body.destroy(); rock.destroy(); //console.log("destroyed?"); };}// This is the function that creates an asteroidfunction asteroids(x, y) { //console.log("asteroid at " + x + "," + y); var circleSize = Math.random() * 50 + 60; var circles = game.add.graphics(0, 0); circles.beginFill('0xffffff'); circles.lineStyle(1, 0xffffff); circles.drawCircle(0, 0, circleSize); circles.endFill(); asteroid = game.add.sprite(x, y); game.physics.p2.enable(asteroid, false); asteroid.addChild(circles); asteroid.body.addCircle(circleSize/3); asteroid.body.setCollisionGroup(asteroidCollisionGroup); asteroid.body.collides([shipCollisionGroup, asteroidCollisionGroup]); asteroid.body.velocity.x = Math.random() * 50 - 25; asteroid.body.velocity.y = Math.random() * 50 - 25; this.spacerocks.add(asteroid); }Full Source: var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'game_div', { preload: preload, create: create, update: update, render: render });function preload() { game.load.image('ship', 'ship.png'); game.load.audio('music', 'music.wav'); game.load.image('square', 'square.png'); game.load.image('dial', 'dial.png'); game.world.setBounds(0, 0, 800*100, 600*100);}var sprite;var shapeSprite;var cursors;var fuelRatio = {"value":1};var graphics;var beenhere = 0;var shipCollisionGroup;var asteroidCollisionGroup;var asteroid;var spacerocks;var threshold = {"x": 0, "y":0};var loss = false;var reset = {"x":0, "y":0};var textdisplay;var fuelLoc = {"x":0, "y":0};var dial;var fuelPodSprite;var refilling = false;function create() { music = game.add.audio('music'); music.play(); game.stage.backgroundColor = "#000000"; game.physics.startSystem(Phaser.Physics.P2JS); spacerocks = game.add.group(); game.physics.p2.setImpactEvents(true); game.physics.p2.restitution = 0.8; shipCollisionGroup = game.physics.p2.createCollisionGroup(); asteroidCollisionGroup = game.physics.p2.createCollisionGroup(); beenhere = 0; // This will run in Canvas mode, so let's gain a little speed and display game.renderer.clearBeforeRender = true; game.renderer.roundPixels = true; // We need arcade physics graphics = game.add.graphics(0, 0); graphics.fixedToCamera = true; fuelPod(400*100, 300*100); // Our player ship sprite = game.add.sprite(400*100, 300*100, 'ship'); sprite.anchor.set(0.5); sprite.angle = 90; sprite.scale.x = .5; sprite.scale.y = .5; // and its physics settings game.physics.enable(sprite, Phaser.Physics.P2JS); sprite.body.addCircle(5); sprite.body.setCollisionGroup(shipCollisionGroup); sprite.body.damping = .1; sprite.body.angularDamping = .99; sprite.anchor.setTo(0.5,0.5); sprite.name = 'sprite'; sprite.body.collides(asteroidCollisionGroup, gotHit, this); threshold.x = sprite.x; threshold.y = sprite.y; cursors = game.input.keyboard.createCursorKeys(); spacebar = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR); game.camera.follow(sprite); fuelArrowSpawn(); fuelRemaining(); asteroidGen();}function asteroidGen(dir) { console.log("dir: " + dir); var xer = 0; var yer = 0; for (var b = 0; b < 10; b++) { if (dir == "right") { xer = sprite.x + 400 + Math.random() * 800; yer = sprite.y - 300 + Math.random() * 1200; } else if (dir == "down") { xer = sprite.x - 1200 + Math.random() * 1600; yer = sprite.y + 300 + Math.random() * 600; } else if (dir == "left") { xer = sprite.x - 400 - Math.random() * 800; yer = sprite.y - 900 + Math.random() * 1200; } else if (dir == "up") { xer = sprite.x - 400 + Math.random() * 1600; yer = sprite.y - 300 - Math.random() * 600; } else { xer = sprite.x - 800 + Math.random() * 1600; yer = sprite.y - 600 + Math.random() * 1200; asteroids(xer, yer); xer = sprite.x - 800 + Math.random() * 1600; yer = sprite.y - 600 + Math.random() * 1200; } asteroids(xer, yer); } }function toRadians (angle) { return angle / (180 / Math.PI);}function explode() { var explosion = game.add.emitter(sprite.x, sprite.y); explosion.makeParticles('square'); explosion.setScale(.2, 1, .2, 1, 0); explosion.setRotation(500,1000); explosionarea = new Phaser.Rectangle(-1, -1, 2, 2); explosion.gravity = 0; explosion.area = this.explosionarea; explosion.start(true, 10000, null, 20); explosion.setAlpha(0, 1, 10000, Phaser.Easing.Linear.None ); explosion.update();}function fuelCheck() { if (Math.sqrt(Math.pow((sprite.x - fuelPodSprite.x), 2) + Math.pow((sprite.y - fuelPodSprite.y), 2)) < 15) fuelGet();}function fuelGet() { //console.log("fuelPodSprite.x: " + fuelPodSprite.x); var moveX = Math.random() * 2000 - 1000; var moveY = Math.random() * 2000 - 1000; fuelPodSprite.body.x = fuelPodSprite.body.x + moveX; fuelPodSprite.body.y = fuelPodSprite.body.y + moveY; game.add.tween(fuelRatio).to({"value":1}, 500, Phaser.Easing.Linear.None, true); refilling = true; fuelLoc.x = fuelPodSprite.body.x; fuelLoc.y = fuelPodSprite.body.y; console.log("fuelPodSprite.x: " + fuelPodSprite.x); }function thrustExhaust() { var exhaust = game.add.emitter(sprite.x, sprite.y); exhaust.makeParticles('square'); exhaust.setScale(.2, .3, .2, .3, 0); exhaust.setRotation(500,1000); //console.log("rotations in pi: " + sprite.rotation/3.141592); var theangle = toRadians(sprite.angle); var xVec = 0 - Math.sin(theangle); var yVec = Math.cos(theangle); exhaust.setAlpha(1, 0, 500, Phaser.Easing.Quadratic.None ); exhaust.x = sprite.x+xVec*20; exhaust.y = sprite.y + yVec*20; exhaustport = new Phaser.Rectangle(-5, -5, 10, 10); exhaust.area = this.exhaustport; //console.log("Thrust X, Y: " + Math.cos(sprite.rotation) * 300 + "," + Math.sin(sprite.rotation) * 300); var yThrust = yVec * 300 + (sprite.body.velocity.y); var xThrust = xVec * 300 + (sprite.body.velocity.x); exhaust.setYSpeed(yThrust - 100, yThrust + 100); exhaust.setXSpeed(xThrust - 100, xThrust + 100); exhaust.gravity = 0; exhaust.start(true, 5000, null, 25); exhaust.update();}function constantGen() { //console.log("constantGen"); if ((threshold.x + 400) < sprite.x) {asteroidGen("right"); threshold.x = sprite.x; killAsteroids();} if ((threshold.x - 400) > sprite.x) {asteroidGen("left"); threshold.x = sprite.x; killAsteroids();} if ((threshold.y + 300) < sprite.y) {asteroidGen("down"); threshold.y = sprite.y; killAsteroids();} if ((threshold.y - 300) > sprite.y) {asteroidGen("up"); threshold.y = sprite.y; killAsteroids();}}function killAsteroids() { console.log("spacerock count: " + spacerocks.length); spacerocks.forEachAlive(destruction, this); console.log("spacerock count after destruction: " + spacerocks.length);}function destructionForSure(rock) { rock.body.destroy(); rock.kill();}function destruction(rock) { //console.log("check for destruction"); if ((rock.x < (threshold.x - 1000)) || (rock.x > (threshold.x + 1000)) || (rock.y > (threshold.y + 1000)) || (rock.y < (threshold.y - 1000))) { rock.body.destroy(); rock.destroy(); //console.log("destroyed?"); };}function constrainVelocity(sprite, maxVelocity) { var body = sprite.body var angle, currVelocitySqr, vx, vy; vx = body.data.velocity[0]; vy = body.data.velocity[1]; currVelocitySqr = vx * vx + vy * vy; if (currVelocitySqr > maxVelocity * maxVelocity) { angle = Math.atan2(vy, vx); vx = Math.cos(angle) * maxVelocity; vy = Math.sin(angle) * maxVelocity; body.data.velocity[0] = vx; body.data.velocity[1] = vy; console.log('limited speed to: '+maxVelocity); }};function update() { if (cursors.up.isDown) { sprite.body.thrust(200); thrustExhaust(); if (fuelRatio.value > 0) fuelRatio.value -= .002; fuelRemaining(); } else { } if (cursors.left.isDown) { sprite.body.angularVelocity = -5; } else if (cursors.right.isDown) { sprite.body.angularVelocity = 5; } else { } constrainVelocity(sprite, 200); //game.world.wrap(sprite.body, 10, false, true, true); //game.world.wrap(asteroid.body, 10, false, true, true); constantGen(); if ((spacebar.isDown) && (loss == true)) reStart(); fuelArrow(); fuelCheck(); if (refilling == true) fuelRemaining();}function fuelArrowSpawn() { dial = game.add.sprite(750, 50, 'dial'); dial.anchor.set(0.5); dial.angle = -90; dial.scale.x = .5; dial.scale.y = .5; dial.fixedToCamera = true;}function fuelArrow() { //console.log(Math.atan(fuelLoc.y - sprite.y, fuelLoc.x - sprite.x)); dial.rotation = Math.atan2(fuelLoc.y - sprite.y, fuelLoc.x - sprite.x); }function fuelPod(x, y) { var fuelPodCircle = game.add.graphics(0, 0); fuelLoc.x = x; fuelLoc.y = y; fuelPodCircle.beginFill('0xFF0000'); fuelPodCircle.lineStyle(1, 0xFF0000); fuelPodCircle.drawRoundedRect(0, 0, 10, 15, 2); fuelPodSprite = game.add.sprite(x, y); game.physics.p2.enable(fuelPodSprite, false); fuelPodSprite.addChild(fuelPodCircle); fuelPodSprite.name = 'fuelPodSprite'; fuelPodSprite.body.collides([asteroidCollisionGroup]); fuelPodSprite.body.setCollisionGroup(asteroidCollisionGroup); }function asteroids(x, y) { //console.log("asteroid at " + x + "," + y); var circleSize = Math.random() * 50 + 60; var circles = game.add.graphics(0, 0); circles.beginFill('0xffffff'); circles.lineStyle(1, 0xffffff); circles.drawCircle(0, 0, circleSize); circles.endFill(); asteroid = game.add.sprite(x, y); game.physics.p2.enable(asteroid, false); asteroid.addChild(circles); asteroid.body.addCircle(circleSize/3); asteroid.body.setCollisionGroup(asteroidCollisionGroup); asteroid.body.collides([shipCollisionGroup, asteroidCollisionGroup]); asteroid.body.velocity.x = Math.random() * 50 - 25; asteroid.body.velocity.y = Math.random() * 50 - 25; this.spacerocks.add(asteroid); }function gotHit() { explode(); fail();}function fail() { reset.x = sprite.x; reset.y = sprite.y; sprite.kill(); var textstyle = { font: "53px Helvetica", fill: "#FFFFFF" }; textdisplay = game.add.text(50, 50, "press spacebar to restart.", textstyle); textdisplay.fixedToCamera = true; loss = true;}function reStart() { fuelRatio.value = 1; sprite.reset(reset.x, reset.y); textdisplay.destroy(); textdisplay.text = ""; loss = false; fuelRemaining();}function fuelRemaining() { graphics.clear(); graphics.beginFill(0xFFFFFF); graphics.lineStyle(10, 0xFFFFFF, 1); graphics.drawRect(100, 550, 600*fuelRatio.value, 10); if (fuelRatio.value == 1) refilling = false;}function render() {}
  9. gregkarber

    My game works, but I want it to work faster

    And will I need to apply the P2 bodies each time I create one? I'm sorry to keep posting questions.
  10. gregkarber

    My game works, but I want it to work faster

    Maybe it would be easier if I just created a circle graphic rather than drawing them with Graphics. I assumed that drawing them would be faster than displaying a .png, but maybe that's wrong.
  11. gregkarber

    My game works, but I want it to work faster

    I'm pretty sure I know how to do that for sprites with images: asteroidGroup = game.add.group();asteroidGroup.createMultiple(200, "asteroid");But how do I do it with graphics? Do I need to use Bitmap Data? I haven't used that at all, but I'm studying up on it now. If anybody knows how to do this, it would be an enormous help for me. Thank you so much!
  12. gregkarber

    Can't figure out collide with a .CSV tilemap

    My problem was the use of "scale" on the tilemap layer. I should have used setScale.
  13. I cannot for the life of me figure out why this isn't working. I keep going over it, and I know I'm missing something obvious. You can play it here to see what I'm talking about. Please help! var TILE = 64;var game = new Phaser.Game(8*TILE, 8*TILE, Phaser.AUTO, 'game_div');var game_what = {};game_what.main = function() { };game_what.main.prototype = { preload: function() { this.game.load.spritesheet('pengy', 'pengy.png', 16, 16); this.game.load.tilemap('map', 'world.csv', null, Phaser.Tilemap.CSV); this.game.load.image('tiles', 'terrain.png'); this.game.world.setBounds(0*TILE, 0*TILE, 8*TILE, 30*TILE); this.game.stage.backgroundColor = "#FFFFFF"; this.cursor = this.game.input.keyboard.createCursorKeys(); }, create: function() { game.physics.startSystem(Phaser.Physics.ARCADE); this.load_map(); this.pengy = this.game.add.sprite(15*TILE, 20*TILE, 'pengy', 0); this.pengydance = this.pengy.animations.add('dance', [0, 1, 0, 2], 9, true); this.pengy.scale.x = 4; this.pengy.scale.y = 4; this.pengy.smoothed = false; this.pengy.anchor.x = .5; this.pengy.anchor.y = 1; game.physics.enable(this.pengy, Phaser.Physics.ARCADE); this.pengy.body.drag.x = 450; this.pengy.body.gravity.y = 700; this.pengy.body.setSize(8, 11); game.camera.follow(this.pengy); this.text = { font: "53px Helvetica", fill: "#000000" }; //this.istext = game.add.text(4*TILE, 1*TILE, "you win", this.isstyle); }, load_map: function() { this.map = this.game.add.tilemap('map', 16, 16); this.map.addTilesetImage('tiles'); this.map.setCollisionBetween(0, 14); //this.map.setCollisionBetween(0, 3, true); //this.map.setCollisionBetween(8,14), true; this.alayer = this.map.createLayer(0); this.alayer.scale.x = 4; this.alayer.scale.y = 4; this.alayer.smoothed = false; this.alayer.resizeWorld(); this.alayer.debug = true; }, pengyfunc: function() { if (this.pengydance.isPlaying == false) this.pengydance.play(); }, tryjump: function() { if (this.cursor.up.isDown && this.pengy.body.touching.down) {this.pengy.body.velocity.y = -450;} }, lose: function() { this.pengy.kill(); }, done: function() { console.log("done") }, update: function() { this.game.physics.arcade.collide(this.alayer, this.pengy, this.done); if (this.cursor.right.isDown && (this.pengy.body.touching.right == false)) {console.log("right"); this.pengyfunc(); this.pengy.body.velocity.x = 180;} else if (this.cursor.left.isDown && (this.pengy.body.touching.left == false)) {this.pengyfunc(); this.pengy.body.velocity.x = -180;} else this.pengydance.stop(); if (this.cursor.up.isDown) this.tryjump(); }, render: function() { this.game.debug.body(this.pengy); }};game.state.add('main', game_what.main);game.state.start('main');
  14. EDIT: I have decided to load and delete sprites around the borders of the viewable space. However, I'm having problems implementing this, as well. Please help. I am working on a game where you play a head of lettuce that rolls, jumps, double-jumps, and wall-bounces up a procedurally generated cliff. I want this to go on for as long as possible, until you finally reach the top. The first two implementations I attempted were both fruitless. First I tried to make the whole thing as sprites. Then I tried to make the whole thing with tiles (using .putTile, as I describe below). Then I tried to make it with tiles, but only place a couple rows at a time. All too slow. So I abandoned the idea of using sprites and taught myself how to use the tilemap. Now I use .putTile to place all of the tiles. (I included the code that I used below, and believe me, I know how bad it is.) However, if I loaded more than a couple rows of it at the start, the game became quite slow. What should I do? I am a bad programmer, so it takes me awhile to implement any of these. 1. Is there a more computationally efficient way to keep doing what I'm doing (placing tiles as the player gets close to them), perhaps without creating so many layers? 2. Generate the entire mountain as an array before starting, and then generate the blocks as sprites as the player gets near them. (This is what I would try next, as I how how to use arrays for proximity-based sprite generation because I used those in my first game)? 3. Generate the level either before or during as a tilemap, and place the tiles as we get near them? 4. Bite the bullet and break it into levels or stages, and swap them out at certain times? 5. Make it so that a fall always kills you, rather than allowing you to climb back up? The idea of falling down a huge thing seemed really hilarious to me, so I would hate to do this, but if I have to... Basically, I want to know which of these is most likely to scale the best, because I really want my mountain to be freaking huge, and I lack the knowledge to understand which implementations will work. Please help, or point me in the right direction, or tell me what I'm doing oh-so-wrong. In the meantime, I'll be working on implementation 2. Hopefully that'll work. create: function() { this.map = game.add.tilemap(); this.map.addTilesetImage('terrain', 'square', 64, 64, 0, 0); this.superlayer = new Array(); this.the_tower = new Array(); this.tower_height = 1; this.load_start = 15;},this.build_tower: function() this.superlayer[layer] = this.map.create('tower', HEIGHT, HEIGHT, 64, 64); this.superlayer[layer].scrollFactorX = 1; this.superlayer[layer].scrollFactorY = 1; for (var i=this.load_start; i<this.load_start+3; i++) { this.randchecker = Math.floor(Math.random()*4); this.tower_height += this.randchecker; if (this.randchecker == 3) this.create_platform(i,HEIGHT-this.tower_height); for (var k = HEIGHT-this.tower_height; k < HEIGHT-1; k++) { this.map.putTile(0, i, k, this.layer1); if ((k == HEIGHT-this.tower_height) && (Math.floor(Math.random()*2) == 0)) this.plant_tree(i, k-1); } } this.map.setCollision(0); this.the_tower[layer] = game.physics.p2.convertTilemap(this.map, this.superlayer[layer], true, true); for (var p = 0; p < this.the_tower[layer].length; p++) this.the_tower[layer][p].setMaterial(this.platformMaterial); this.load_start += 3;},update: function() { this.new_computation = 3*TILE*this.threshold; if (this.lettuce.x > this.new_computation) { if (this.switcher[this.threshold] == false) { this.switcher[this.threshold] = true; this.tower_build(this.threshold); this.threshold++; } }}
  15. gregkarber

    Efficient way to generate a random mountain to climb

    I couldn't get them to without killing them. I would love for someone to help with that. However, you just helped me figure out a huge thing. I have been loading individual square sprites, but almost 99% of them are columns. So I only loaded physics bodies on the top ones. However, I could massively reduce the number of sprites by making each sprite a column. So thanks!
  16. gregkarber

    P2 Sprites not colliding when .outOfBoundsKill = true;

    I tried writing a function that deletes sprites when they exit the camera viewpoint, thinking that outOfBoundsKill was where the problem was, but it still occurs. It seems like sprites summoned using .reset that have already been created and killed don't pull their bodies with them, and even if you enable the body again, nothing happens. **EDIT:** Based on this theory, I fixed it by adding sprite.body.destroy() before I killed each sprite. Is there some way to do that with sprite.outOfBoundsKill = true, but I couldn't figure it out.
  17. I am working on an infinite climber of sorts, and I'm trying to create tiles on the side of the screen the player is going. However, if I enable .checkWorldBounds and .outOfBoundsKill, which is required for performance, the tiles that are created do not collide with my sprite. place_block: function(x,y) { x = x*TILE; y = y*TILE; var ground = this.platforms.getFirstDead(); ground.reset(x,y); game.physics.p2.enable(ground); ground.checkWorldBounds = true; ground.outOfBoundsKill = true; ground.body.static = true; ground.body.setMaterial(this.platformMaterial); },This all works perfectly during my setup, when the only sprites being spawned are the ones currently visible: learn_box: function() { // learn the borders of the box to start this.edges[0] = Math.floor((this.game.camera.view.top)/TILE)-1; this.edges[1] = Math.floor((this.game.camera.view.right)/TILE)-2; this.edges[2] = Math.floor((this.game.camera.view.bottom)/TILE)+1; this.edges[3] = Math.floor((this.game.camera.view.left)/TILE)-1; console.log("up: " + this.edges[0] + " down: " + this.edges[2] + " left: " + this.edges[3] + " right: " + this.edges[1]); }, load_sprites: function(name) { for (var b = this.edges[3]; b <= this.edges[1]; b++) { for (var c = this.edges[0]; c <= this.edges[2]; c++) { if (this.tile_lookup(b,c) == "1") this.place_block(b,c); } } },However, for sprites that are created with the following code, it doesn't work: check_new: function() { // checks to see if new borders exist this.newedge[0] = Math.floor((this.game.camera.view.top)/TILE)-1; this.newedge[1] = Math.floor((this.game.camera.view.right)/TILE)+1; this.newedge[2] = Math.floor((this.game.camera.view.bottom)/TILE)+1; this.newedge[3] = Math.floor((this.game.camera.view.left)/TILE)-1; if (this.newedge[0] < this.edges[0]) this.load_line(0); if (this.newedge[0] > this.edges[0]) this.load_line(2); if (this.newedge[1] < this.edges[1]) this.load_line(3); if (this.newedge[1] > this.edges[1]) this.load_line(1); this.new_to_old(); }, new_to_old: function() { for (var a = 0; a < 4; a++) this.edges[a] = this.newedge[a]; }, load_line: function(dir) { //console.log("dir: " + dir); for (var c = this.newedge[((dir + 3) % 4)]; c <= this.newedge[((dir+1) % 4)]; c++) { if ((dir % 2) == 0) { if (this.tile_lookup(c, this.newedge[dir]) == "1") this.place_block(c, this.newedge[dir]); } else if (this.tile_lookup(this.newedge[dir], c) == "1") this.place_block(this.newedge[dir], c); } },Even if I adjust it to not create the ground sprites until they are visible on-screen, it still seems to create empty sprites, sprites that are visible but do not seem to have their P2 physics bodies enabled. If I comment out .outOfBoundsKill and .checkWorldBounds, then it works as intended, but of course I quickly run out of sprites to use (and it gets real slow real quick). Can anybody see what my problem is? Any help would be great. I'm so frustrated at my inability to figure this out. EDIT: It occurred to me that you guys might want my create() code, as well. Here it is: create: function() { this.game.world.setBounds(0*TILE, 0*TILE, 100*TILE, 100*TILE); game.physics.startSystem(Phaser.Physics.P2JS); game.physics.p2.defaultRestitution = 0.8; game.physics.p2.gravity.y = 300; game.physics.p2.setImpactEvents(true); //var mountain_group = game.physics.p2.createCollisionGroup(); //var lettuce_collide = game.physics.p2.createCollisionGroup(); this.last_platform = 0; this.trees1 = game.add.group(); this.trees1.createMultiple(200, 'tree1'); this.trees2 = game.add.group(); this.trees2.createMultiple(200, 'tree2'); this.trees3 = game.add.group(); this.trees3.createMultiple(200, 'tree3'); this.lettuce = this.game.add.sprite(4*TILE, 88*TILE, 'lettuce'); game.physics.p2.enable(this.lettuce); this.spriteMaterial = game.physics.p2.createMaterial('spriteMaterial', this.lettuce.body); this.worldMaterial = game.physics.p2.createMaterial('worldMaterial'); this.platformMaterial = game.physics.p2.createMaterial('platformMaterial'); this.smoothMaterial = game.physics.p2.createMaterial('smoothMaterial'); this.edges = new Array(); this.newedge = new Array(); this.lettuce.scale.x = .5; this.lettuce.scale.y = .5; this.lettuce.body.setCircle(11); this.lettuce.body.dynamic = true; //this.lettuce.body.applyDamping(500); this.lettuce.body.data.gravityScale = 5; this.platforms = game.add.group(); this.platforms.createMultiple(100, 'square'); //this.lettuce.body.setCollisionGroup(lettuce_collide); //this.lettuce.body.collides(mountain_group); var space_key = this.game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR); space_key.onDown.add(this.jump, this); this.cursors = game.input.keyboard.createCursorKeys(); this.game.camera.position.y = this.lettuce.y; this.game.camera.setPosition(this.lettuce.x, this.lettuce.y); this.lettuce.body.setMaterial(this.spriteMaterial); // 4 trues = the 4 faces of the world in left, right, top, bottom order game.physics.p2.setWorldMaterial(this.worldMaterial, true, true, true, true); var contactMaterial = game.physics.p2.createContactMaterial(this.spriteMaterial, this.platformMaterial); contactMaterial.friction = 7; // Friction to use in the contact of these two materials. contactMaterial.restitution = 0; // Restitution (i.e. how bouncy it is!) to use in the contact of these two materials. contactMaterial.stiffness = 1e7; // Stiffness of the resulting ContactEquation that this ContactMaterial generate. contactMaterial.relaxation = 10; // Relaxation of the resulting ContactEquation that this ContactMaterial generate. contactMaterial.frictionStiffness = 1e7; // Stiffness of the resulting FrictionEquation that this ContactMaterial generate. contactMaterial.frictionRelaxation = 3; // Relaxation of the resulting FrictionEquation that this ContactMaterial generate. contactMaterial.surfaceVelocity = 0; // Will add surface velocity to this material. If bodyA rests on top if bodyB, and the surface velocity is positive, bodyA will slide to the right. var contactMaterial2 = game.physics.p2.createContactMaterial(this.smoothMaterial, this.platformMaterial); contactMaterial2.friction = 0; // Friction to use in the contact of these two materials. contactMaterial2.restitution = 0; // Restitution (i.e. how bouncy it is!) to use in the contact of these two materials. contactMaterial2.stiffness = 1e7; // Stiffness of the resulting ContactEquation that this ContactMaterial generate. contactMaterial2.relaxation = 10; // Relaxation of the resulting ContactEquation that this ContactMaterial generate. contactMaterial2.frictionStiffness = 1e7; // Stiffness of the resulting FrictionEquation that this ContactMaterial generate. contactMaterial2.frictionRelaxation = 3; // Relaxation of the resulting FrictionEquation that this ContactMaterial generate. contactMaterial2.surfaceVelocity = 0; // Will add surface velocity to this material. If bodyA rests on top if bodyB, and the surface velocity is positive, bodyA will slide to the right. this.learn_box(); this.clear_grid(); this.build_ground(); this.load_sprites(); this.game.camera.follow(this.lettuce); },Thank you, anybody who might help.
  18. gregkarber

    Efficient way to generate a random mountain to climb

    Thank you very much! I'm working on an implementation with sprites that are created on the edges and have .outOfBoundsKill = true. However, sprites that are created with this function don't seem to hold onto the physics bodies I'm trying to give them. Can anyone help? I posted a new thread about it here. I have become so frustrated with my own ignorance and inability. Coding's hard, y'all.
  19. gregkarber

    Open Window on Home Screen

    I have been working on a casual game and am trying to make it possible for people to tweet and/or Facebook their score. I have accomplished this through the use of window.open and the intent link for Twitter and the sharer link for Facebook. This works absolutely fine on browsers, even on mobile. However, I want to encourage people to add the page to their iOS home screen, and if they do this, neither of these links work (because it's not in a browser, I assume). Is there an alternative way to do this? Or a way for an iOS device to trigger the Twitter and Facebook apps? Thank you very much!
  20. I am not a coder (by any means), but I managed to cobble together this game based on a tortoise character in these daily koans that I write. You can play the game at koanoftheday.com/trails.
  21. gregkarber

    Help with First HTML5 Game

    Okay, more thoroughly useless investigation: I have found that the bottom of your playfield seems to be at about 150, that is, when the green dot is at the bottom of the square, the y location seems to be 150. Not sure if this helps!
  22. gregkarber

    Help with First HTML5 Game

    I just tried debugging it, and found that "head.x" did equal 255 when it said that the snake was dead, despite it not looking -- visually -- as if the sneak were at the edge. I also noticed that the snake can go well below the visual boundary before it says that the snake is dead. I am a rank amateur, so this is all I can say right now.
  23. gregkarber

    Audio Static after Many Plays of a Sound Effect [FIXED]

    I just re-tested it in Google Chrome, and now it's happening around the 950 step mark (or after about 300 sound-effect cues). I think the increase might have happened since I converted the sound files to lower-fidelity versions. And sometimes now it doesn't get distorted, it just decides to stop playing all-together. Once this happens, no sound effects work. I see some people include end-point parameters in their sound cues. Perhaps doing that will help? I honestly have no experience in audio programming and so do not even know where to begin. Is overlapping causing this kind of corruption? Thank you very much for testing it out! EDIT: Just saw your suggestion! Will do.
  24. I have been working on a tile-based rogue-like exploration game that is supposed to be very relaxing and peaceful. A lot of it is procedurally generated, and I wanted to procedurally generate the music, too. So I loaded two octaves of notes in the pentatonic scale: this.game.load.audio('notec', ['../wp-content/themes/toolbox/js/assets/music/notec.ogg','../wp-content/themes/toolbox/js/assets/music/notec.mp3']);this.game.load.audio('noted', ['../wp-content/themes/toolbox/js/assets/music/noted.ogg','../wp-content/themes/toolbox/js/assets/music/noted.mp3']);this.game.load.audio('notee', ['../wp-content/themes/toolbox/js/assets/music/notee.ogg','../wp-content/themes/toolbox/js/assets/music/notee.mp3']);this.game.load.audio('noteg', ['../wp-content/themes/toolbox/js/assets/music/noteg.ogg','../wp-content/themes/toolbox/js/assets/music/noteg.mp3']);this.game.load.audio('notea', ['../wp-content/themes/toolbox/js/assets/music/notea.ogg','../wp-content/themes/toolbox/js/assets/music/notea.mp3']);this.game.load.audio('notec2', ['../wp-content/themes/toolbox/js/assets/music/notec2.ogg','../wp-content/themes/toolbox/js/assets/music/notec2.mp3']);this.game.load.audio('noted2', ['../wp-content/themes/toolbox/js/assets/music/noted2.ogg','../wp-content/themes/toolbox/js/assets/music/noted2.mp3']);this.game.load.audio('notee2', ['../wp-content/themes/toolbox/js/assets/music/notee2.ogg','../wp-content/themes/toolbox/js/assets/music/notee2.mp3']);this.game.load.audio('noteg2', ['../wp-content/themes/toolbox/js/assets/music/noteg2.ogg','../wp-content/themes/toolbox/js/assets/music/noteg2.mp3']);this.game.load.audio('notea2', ['../wp-content/themes/toolbox/js/assets/music/notea2.ogg','../wp-content/themes/toolbox/js/assets/music/notea2.mp3']);And then I called a function every time the person took a step: sound_track: function() { // random music generation if ((stepcounter % 2) == 1) { ckey = game.add.audio('notec'); dkey = game.add.audio('noted'); ekey = game.add.audio('notee'); gkey = game.add.audio('noteg'); akey = game.add.audio('notea'); c2key = game.add.audio('notec'); d2key = game.add.audio('noted'); e2key = game.add.audio('notee'); g2key = game.add.audio('noteg'); a2key = game.add.audio('notea'); ckey.volume = .3; dkey.volume = .3; ekey.volume = .3; gkey.volume = .3; akey.volume = .3; c2key.volume = .3; d2key.volume = .3; e2key.volume = .3; g2key.volume = .3; a2key.volume = .3; console.log("this part's working"); var randtime = Math.floor(Math.random()*8)+1; var randmusic = Math.floor(Math.random()*12)+1; if ((randtime == 1) || ((stepcounter % 4) == 1)) { // guaranteed beat console.log(randmusic); if (randmusic == 1 || randmusic == 11) ckey.play(); if (randmusic == 2) dkey.play(); if (randmusic == 3) ekey.play(); if (randmusic == 4) gkey.play(); if (randmusic == 5) akey.play(); if (randmusic == 6) c2key.play(); if (randmusic == 7) d2key.play(); if (randmusic == 8) e2key.play(); if (randmusic == 9) g2key.play(); if (randmusic == 10) a2key.play(); } } },Which seemed to work fine! (Albeit a bit random: I need to write a few more rules, perhaps a bassline, to give the song more structure. But it's already very zen!) Anyway, this works great for the first hundred or so steps, but then the audio starts to get all staticky. Eventually, it stopped playing at all, and I had to reload the window. I thought maybe I could fix this by making the files shorter and more compressed, and I did that, and it seemed to help a bit, but the audio still got pretty corrupted-sounded and eventually stopped all-together. This affects all audio played by the code, even sound effects which have not been played more than a few times, and does not go away if I wait. I am not a programmer, and this is just a side project for me. So it's very possible that I am doing something silly, or stupid, or preposterously round-about. If so, please correct me! I have really enjoyed the experience of coding in Phaser, and it's been a lot of fun, but this kind of bug (which throws no errors in the console!) totally perplexes me, as it falls outside the realm of internal code-logic and into the realm of technical know-how, of which I have none. (If you would like to test the game out, you can find it a http://www.koanoftheday.com/trails, and the password is trails. It's not completely finished, though, so there might be other bugs!) Also, a PS: I have lurked in these forums and used people's advice to solve a number of issues already. This seems like a great place, and you all seem like great people, and I'm excited to finally register and start contributing (even if my first contribution is a request for help!). Thank you all. EDIT: Well, I think I've figured it out! The problem was that I was doing the "ckey = game.add.audio('notec');" stuff (I'm not actually sure what this is called, only how it functions!) every single time the sound effects were called. This was overloading something and making the sound sound horrible. Hopefully somebody else will do the same stupid thing and this post will serve as helpful information to them!
  25. gregkarber

    Audio Static after Many Plays of a Sound Effect [FIXED]

    Oh, wow. I thought I'd tried it on a few people's computers in a few different browsers. May I ask what browser you're using?