gregkarber

My game works, but I want it to work faster

Recommended Posts

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() {}

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites

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);	}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.