/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Asteroid class
var Asteroid = Container.expand(function () {
	var self = Container.call(this);
	// Attach asteroid asset
	var asteroidGraphics = self.attachAsset('asteroid', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Set asteroid speed
	self.speed = 3;
	// Update function called every game tick
	self.update = function () {
		// Move asteroid based on speed
		self.y += self.speed;
		// Destroy asteroid when it gets out of player screen
		if (self.y > 2732) {
			self.destroy();
		}
		// Check for collision with player
		if (self.intersects(player)) {
			// Add a blasting effect
			var blast = self.attachAsset('blast', {
				anchorX: 0.5,
				anchorY: 0.5
			});
			blast.x = player.x;
			blast.y = player.y;
			game.addChild(blast);
			// Destroy the blast effect after a short delay
			LK.setTimeout(function () {
				blast.destroy();
			}, 500);
			// Play blast sound effect
			LK.getSound('blastSound').play();
			// Play blast sound effect
			LK.getSound('blastSound').play();
			// Trigger game over when asteroid hits player
			LK.showGameOver();
		}
	};
});
// Bullet class
var Bullet = Container.expand(function () {
	var self = Container.call(this);
	// Attach bullet asset
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Set bullet speed
	self.speed = -14;
	// Update function called every game tick
	self.update = function () {
		self.y += self.speed;
		// Check for collision with enemy and asteroid
		// Use spatial partitioning to optimize collision detection
		// Custom grid implementation for spatial partitioning
		var grid = {
			width: 2048,
			height: 2732,
			cellSize: 100,
			cells: {},
			insert: function insert(obj) {
				var cellX = Math.floor(obj.x / this.cellSize);
				var cellY = Math.floor(obj.y / this.cellSize);
				var key = cellX + ',' + cellY;
				if (!this.cells[key]) {
					this.cells[key] = [];
				}
				this.cells[key].push(obj);
			},
			retrieve: function retrieve(obj) {
				var cellX = Math.floor(obj.x / this.cellSize);
				var cellY = Math.floor(obj.y / this.cellSize);
				var key = cellX + ',' + cellY;
				return this.cells[key] || [];
			},
			clear: function clear() {
				this.cells = {};
			}
		};
		game.children.forEach(function (child) {
			if (child instanceof Enemy || child instanceof Asteroid) {
				grid.insert(child);
			}
		});
		var nearbyTargets = grid.retrieve(self);
		for (var i = 0; i < nearbyTargets.length; i++) {
			var target = nearbyTargets[i];
			if (self.intersects(target)) {
				// Destroy target and bullet on collision
				target.destroy();
				self.destroy();
				// Play blast sound effect
				LK.getSound('blastSound').play();
				// Increase score by 50 points when target dies
				LK.setScore(LK.getScore() + 50);
				// Update the scoreboard
				scoreTxt.setText(LK.getScore());
				// Add a blasting effect
				var blast = self.attachAsset('blast', {
					anchorX: 0.5,
					anchorY: 0.5
				});
				blast.x = self.x;
				blast.y = self.y;
				game.addChild(blast);
				// Destroy the blast effect after a short delay
				LK.setTimeout(function () {
					blast.destroy();
				}, 500);
				break;
			}
		}
		// Destroy bullet when it goes past to the screen
		if (self.y < 0) {
			self.visible = false;
			game.bulletPool.push(self);
		}
	};
	// Add a reset method to reset bullet properties
	self.reset = function () {
		self.visible = true;
		self.y = player.y;
	};
});
// Enemy class
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	// Attach enemy asset
	var enemyGraphics = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Set enemy speed
	self.speed = 5;
	// Update function called every game tick
	self.update = function () {
		// Move enemy based on speed
		self.y += self.speed;
		// Destroy enemy when it gets out of player screen
		if (self.y > 2732) {
			self.destroy();
		}
		// Enemy fires a bullet every 60 ticks
		if (LK.ticks % 60 == 0) {
			var enemyBullet = game.addChild(new EnemyBullet());
			// Set bullet initial position to enemy's position
			enemyBullet.x = self.x;
			enemyBullet.y = self.y;
			// Set bullet speed to move downwards
			enemyBullet.speed = 10;
		}
	};
});
// EnemyBullet class
var EnemyBullet = Container.expand(function () {
	var self = Container.call(this);
	// Attach bullet asset
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Set bullet speed
	self.speed = 5;
	// Update function called every game tick
	self.update = function () {
		self.y += self.speed;
		// Check for collision with player
		if (self.intersects(player)) {
			// Add a blasting effect
			var blast = self.attachAsset('blast', {
				anchorX: 0.5,
				anchorY: 0.5
			});
			blast.x = player.x;
			blast.y = player.y;
			game.addChild(blast);
			// Destroy the blast effect after a short delay
			LK.setTimeout(function () {
				blast.destroy();
			}, 500);
			// Play blast sound effect
			LK.getSound('blastSound').play();
			// Play blast sound effect when player is destroyed by enemy bullet
			LK.getSound('blastSound').play();
			// Trigger game over when bullet hits player
			LK.showGameOver();
		}
	};
});
// Player class
var Player = Container.expand(function () {
	var self = Container.call(this);
	// Attach player asset
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Set player speed
	self.speed = 5;
	// Update function called every game tick
	self.update = function () {
		// Player movement is handled in game.move event
	};
});
/**** 
* Initialize Game
****/ 
//<Assets used in the game will automatically appear here>
//<Write imports for supported plugins here>
var game = new LK.Game();
/**** 
* Game Code
****/ 
LK.playMusic('ourBackgroundMusic');
//<Assets used in the game will automatically appear here>
//<Write imports for supported plugins here>
//<Assets used in the game will automatically appear here>
//<Write imports for supported plugins here>
var background = game.attachAsset('background', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 1024,
	y: 1366,
	scaleX: game.width / LK.getAsset('background', {}).width,
	scaleY: game.height / LK.getAsset('background', {}).height
});
// Create a scoreboard and display it on the screen
var scoreTxt = new Text2('0', {
	size: 150,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
game.update = function () {
	// Spawn an enemy every 30 ticks and an asteroid every 40 ticks
	if (LK.ticks % 60 == 0) {
		var enemy = game.addChild(new Enemy());
		// Set enemy initial position 
		enemy.x = Math.random() * 2048;
		enemy.y = 0;
	}
	if (LK.ticks % 80 == 0) {
		var asteroid = game.addChild(new Asteroid());
		// Set asteroid initial position 
		asteroid.x = Math.random() * 2048;
		asteroid.y = 0;
	}
	// Move enemies and asteroids continuously downwards
	// Define a global grid object for spatial partitioning
	var grid = {
		width: 2048,
		height: 2732,
		cellSize: 100,
		cells: {},
		insert: function insert(obj) {
			var cellX = Math.floor(obj.x / this.cellSize);
			var cellY = Math.floor(obj.y / this.cellSize);
			var key = cellX + ',' + cellY;
			if (!this.cells[key]) {
				this.cells[key] = [];
			}
			this.cells[key].push(obj);
		},
		retrieve: function retrieve(obj) {
			var cellX = Math.floor(obj.x / this.cellSize);
			var cellY = Math.floor(obj.y / this.cellSize);
			var key = cellX + ',' + cellY;
			return this.cells[key] || [];
		},
		clear: function clear() {
			this.cells = {};
		}
	};
	// Use the grid to optimize updates
	grid.clear(); // Clear the grid before inserting new objects
	game.children.forEach(function (child) {
		if (child instanceof Enemy || child instanceof Asteroid) {
			grid.insert(child);
		}
	});
	var visibleObjects = grid.retrieve(player);
	visibleObjects.forEach(function (child) {
		child.y += 5;
		// Destroy any object that passes behind the player
		if (child.y > player.y + player.height / 2) {
			child.destroy();
		}
	});
};
var player = game.addChild(new Player());
// Set player initial position
player.x = 1024;
player.y = 2732 - player.height / 2 - 300;
// Add mouse move event to the game
game.move = function (x, y, obj) {
	// Move player only on x axis
	player.x = x;
};
game.down = function (x, y, obj) {
	// Create a bullet instance
	// Use a bullet pool to optimize bullet creation
	if (!game.bulletPool) {
		game.bulletPool = [];
	}
	var bullet;
	if (game.bulletPool.length > 0) {
		bullet = game.bulletPool.pop();
		bullet.visible = true;
	} else {
		bullet = game.addChild(new Bullet());
	}
	bullet.reset(); // Reset bullet properties
	LK.getSound('fireBullet').play();
	// Set bullet initial position to player's position
	bullet.x = player.x;
	bullet.y = player.y;
};
// Update the scoreboard every game tick
scoreTxt.setText(LK.getScore()); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Asteroid class
var Asteroid = Container.expand(function () {
	var self = Container.call(this);
	// Attach asteroid asset
	var asteroidGraphics = self.attachAsset('asteroid', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Set asteroid speed
	self.speed = 3;
	// Update function called every game tick
	self.update = function () {
		// Move asteroid based on speed
		self.y += self.speed;
		// Destroy asteroid when it gets out of player screen
		if (self.y > 2732) {
			self.destroy();
		}
		// Check for collision with player
		if (self.intersects(player)) {
			// Add a blasting effect
			var blast = self.attachAsset('blast', {
				anchorX: 0.5,
				anchorY: 0.5
			});
			blast.x = player.x;
			blast.y = player.y;
			game.addChild(blast);
			// Destroy the blast effect after a short delay
			LK.setTimeout(function () {
				blast.destroy();
			}, 500);
			// Play blast sound effect
			LK.getSound('blastSound').play();
			// Play blast sound effect
			LK.getSound('blastSound').play();
			// Trigger game over when asteroid hits player
			LK.showGameOver();
		}
	};
});
// Bullet class
var Bullet = Container.expand(function () {
	var self = Container.call(this);
	// Attach bullet asset
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Set bullet speed
	self.speed = -14;
	// Update function called every game tick
	self.update = function () {
		self.y += self.speed;
		// Check for collision with enemy and asteroid
		// Use spatial partitioning to optimize collision detection
		// Custom grid implementation for spatial partitioning
		var grid = {
			width: 2048,
			height: 2732,
			cellSize: 100,
			cells: {},
			insert: function insert(obj) {
				var cellX = Math.floor(obj.x / this.cellSize);
				var cellY = Math.floor(obj.y / this.cellSize);
				var key = cellX + ',' + cellY;
				if (!this.cells[key]) {
					this.cells[key] = [];
				}
				this.cells[key].push(obj);
			},
			retrieve: function retrieve(obj) {
				var cellX = Math.floor(obj.x / this.cellSize);
				var cellY = Math.floor(obj.y / this.cellSize);
				var key = cellX + ',' + cellY;
				return this.cells[key] || [];
			},
			clear: function clear() {
				this.cells = {};
			}
		};
		game.children.forEach(function (child) {
			if (child instanceof Enemy || child instanceof Asteroid) {
				grid.insert(child);
			}
		});
		var nearbyTargets = grid.retrieve(self);
		for (var i = 0; i < nearbyTargets.length; i++) {
			var target = nearbyTargets[i];
			if (self.intersects(target)) {
				// Destroy target and bullet on collision
				target.destroy();
				self.destroy();
				// Play blast sound effect
				LK.getSound('blastSound').play();
				// Increase score by 50 points when target dies
				LK.setScore(LK.getScore() + 50);
				// Update the scoreboard
				scoreTxt.setText(LK.getScore());
				// Add a blasting effect
				var blast = self.attachAsset('blast', {
					anchorX: 0.5,
					anchorY: 0.5
				});
				blast.x = self.x;
				blast.y = self.y;
				game.addChild(blast);
				// Destroy the blast effect after a short delay
				LK.setTimeout(function () {
					blast.destroy();
				}, 500);
				break;
			}
		}
		// Destroy bullet when it goes past to the screen
		if (self.y < 0) {
			self.visible = false;
			game.bulletPool.push(self);
		}
	};
	// Add a reset method to reset bullet properties
	self.reset = function () {
		self.visible = true;
		self.y = player.y;
	};
});
// Enemy class
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	// Attach enemy asset
	var enemyGraphics = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Set enemy speed
	self.speed = 5;
	// Update function called every game tick
	self.update = function () {
		// Move enemy based on speed
		self.y += self.speed;
		// Destroy enemy when it gets out of player screen
		if (self.y > 2732) {
			self.destroy();
		}
		// Enemy fires a bullet every 60 ticks
		if (LK.ticks % 60 == 0) {
			var enemyBullet = game.addChild(new EnemyBullet());
			// Set bullet initial position to enemy's position
			enemyBullet.x = self.x;
			enemyBullet.y = self.y;
			// Set bullet speed to move downwards
			enemyBullet.speed = 10;
		}
	};
});
// EnemyBullet class
var EnemyBullet = Container.expand(function () {
	var self = Container.call(this);
	// Attach bullet asset
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Set bullet speed
	self.speed = 5;
	// Update function called every game tick
	self.update = function () {
		self.y += self.speed;
		// Check for collision with player
		if (self.intersects(player)) {
			// Add a blasting effect
			var blast = self.attachAsset('blast', {
				anchorX: 0.5,
				anchorY: 0.5
			});
			blast.x = player.x;
			blast.y = player.y;
			game.addChild(blast);
			// Destroy the blast effect after a short delay
			LK.setTimeout(function () {
				blast.destroy();
			}, 500);
			// Play blast sound effect
			LK.getSound('blastSound').play();
			// Play blast sound effect when player is destroyed by enemy bullet
			LK.getSound('blastSound').play();
			// Trigger game over when bullet hits player
			LK.showGameOver();
		}
	};
});
// Player class
var Player = Container.expand(function () {
	var self = Container.call(this);
	// Attach player asset
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Set player speed
	self.speed = 5;
	// Update function called every game tick
	self.update = function () {
		// Player movement is handled in game.move event
	};
});
/**** 
* Initialize Game
****/ 
//<Assets used in the game will automatically appear here>
//<Write imports for supported plugins here>
var game = new LK.Game();
/**** 
* Game Code
****/ 
LK.playMusic('ourBackgroundMusic');
//<Assets used in the game will automatically appear here>
//<Write imports for supported plugins here>
//<Assets used in the game will automatically appear here>
//<Write imports for supported plugins here>
var background = game.attachAsset('background', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 1024,
	y: 1366,
	scaleX: game.width / LK.getAsset('background', {}).width,
	scaleY: game.height / LK.getAsset('background', {}).height
});
// Create a scoreboard and display it on the screen
var scoreTxt = new Text2('0', {
	size: 150,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
game.update = function () {
	// Spawn an enemy every 30 ticks and an asteroid every 40 ticks
	if (LK.ticks % 60 == 0) {
		var enemy = game.addChild(new Enemy());
		// Set enemy initial position 
		enemy.x = Math.random() * 2048;
		enemy.y = 0;
	}
	if (LK.ticks % 80 == 0) {
		var asteroid = game.addChild(new Asteroid());
		// Set asteroid initial position 
		asteroid.x = Math.random() * 2048;
		asteroid.y = 0;
	}
	// Move enemies and asteroids continuously downwards
	// Define a global grid object for spatial partitioning
	var grid = {
		width: 2048,
		height: 2732,
		cellSize: 100,
		cells: {},
		insert: function insert(obj) {
			var cellX = Math.floor(obj.x / this.cellSize);
			var cellY = Math.floor(obj.y / this.cellSize);
			var key = cellX + ',' + cellY;
			if (!this.cells[key]) {
				this.cells[key] = [];
			}
			this.cells[key].push(obj);
		},
		retrieve: function retrieve(obj) {
			var cellX = Math.floor(obj.x / this.cellSize);
			var cellY = Math.floor(obj.y / this.cellSize);
			var key = cellX + ',' + cellY;
			return this.cells[key] || [];
		},
		clear: function clear() {
			this.cells = {};
		}
	};
	// Use the grid to optimize updates
	grid.clear(); // Clear the grid before inserting new objects
	game.children.forEach(function (child) {
		if (child instanceof Enemy || child instanceof Asteroid) {
			grid.insert(child);
		}
	});
	var visibleObjects = grid.retrieve(player);
	visibleObjects.forEach(function (child) {
		child.y += 5;
		// Destroy any object that passes behind the player
		if (child.y > player.y + player.height / 2) {
			child.destroy();
		}
	});
};
var player = game.addChild(new Player());
// Set player initial position
player.x = 1024;
player.y = 2732 - player.height / 2 - 300;
// Add mouse move event to the game
game.move = function (x, y, obj) {
	// Move player only on x axis
	player.x = x;
};
game.down = function (x, y, obj) {
	// Create a bullet instance
	// Use a bullet pool to optimize bullet creation
	if (!game.bulletPool) {
		game.bulletPool = [];
	}
	var bullet;
	if (game.bulletPool.length > 0) {
		bullet = game.bulletPool.pop();
		bullet.visible = true;
	} else {
		bullet = game.addChild(new Bullet());
	}
	bullet.reset(); // Reset bullet properties
	LK.getSound('fireBullet').play();
	// Set bullet initial position to player's position
	bullet.x = player.x;
	bullet.y = player.y;
};
// Update the scoreboard every game tick
scoreTxt.setText(LK.getScore());
 Space craft in facing forward. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 spacecraft in 4k
 
 fire blast. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 asteroid. Single Game Texture. In-Game asset. 2d. No shadows
 dark nebula galaxy 4k. Single Game Texture. In-Game asset. 2d. Blank background. No shadows