gregkarber

Members
  • Content Count

    27
  • Joined

  • Last visited

About gregkarber

  • Rank
    Member

Contact Methods

  • Website URL
    http://www.gregkarber.com
  • Twitter
    gregkarber

Profile Information

  • Gender
    Not Telling

Recent Profile Visitors

557 profile views
  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. 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.
  9. 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.
  10. 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!
  11. 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() {}
  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. 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!
  15. 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.