Code edit (1 edits merged)
Please save this source code
User prompt
Create a particle effect class called DropEffect using the same graphics assets as the pickups (excluding shadows). When colliding with an obstruction, create a DropEffect particle which shoots away in a random direction from the player, spinning and shrinking.
Code edit (12 edits merged)
Please save this source code
User prompt
monsters start with a random x flip
Code edit (1 edits merged)
Please save this source code
Code edit (8 edits merged)
Please save this source code
User prompt
Fix Bug: 'ReferenceError: jumpSpeed is not defined' in this line: 'jumpVelocityX = Math.cos(angle) * jumpSpeed;' Line Number: 65
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
Add an effects array to the game class, and add a BloodsplatterEffect class, which lasts for 1s, growing larger and more transparent, and is also affected by the player velocity. When a monster is destroyed after taking a player life, create a BloodsplatterEffect
Code edit (1 edits merged)
Please save this source code
Code edit (10 edits merged)
Please save this source code
User prompt
Add a hitbox to the monster. After updating a monster, check if its hitbox intersects the player's hitbox, causing the player to lose a life
User prompt
The changeScore function should additionally call the LK.setScore function after adjusting the score
User prompt
ensure the score cannot go below zero
User prompt
instead of losing a life when colliding with an obstacle, reduce the score by 1, but keep the invulnerability system
User prompt
instead of losing a life when colliding with an obstacle, reduce the score by 1
Code edit (8 edits merged)
Please save this source code
User prompt
pickups should also have a shadow
Code edit (1 edits merged)
Please save this source code
Code edit (2 edits merged)
Please save this source code
User prompt
the monsters have shadow assets underneath them
Code edit (5 edits merged)
Please save this source code
User prompt
after traveling 10000 distance, spawn a new Monster class at the bottom of the screen that heads towards the player, but is also affected by the VelocityX and VelocityY in it's update function
User prompt
add a monsters array variable to the game class
===================================================================
--- original.js
+++ change.js
@@ -25,63 +25,71 @@
var self = Container.call(this);
parent.addChild(self);
self.x = x;
self.y = y;
+ var active = false;
var updateTick = 0;
- var updatePeriod = 30;
+ var updatePeriod = 60;
var jumpVelocityX = 0;
var jumpVelocityY = 0;
var jumpSpeedMax = 25;
var jumpHeight = 100;
- var jumpDuration = updatePeriod / 3;
+ var jumpDuration = updatePeriod * 2 / 3;
var jumpDistMax = jumpSpeedMax * jumpDuration;
var jumpDistMaxSqr = jumpDistMax * jumpDistMax;
- var despawnDist = 3000;
- var despawnDistSqr = despawnDist * despawnDist;
+ var activationDist = 1000;
+ var activationDistSqr = activationDist * activationDist;
+ var despawnY = -1500;
var shadowReduction = 0.1;
var shadow = self.createAsset('shadow', 'Monster shadow', 0.45, 1);
var graphics = self.createAsset('monster', 'Monster graphics', 0.5, 1);
+ graphics.scale.x = Math.random() < 0.5 ? 1 : -1;
shadow.width = graphics.width * 0.9;
shadow.height = graphics.width * 0.45;
shadow.tint = 0x000000;
shadow.alpha = 0.5;
self.jumping = false;
self.hitbox = shadow;
self.update = update;
function update(velocityX, velocityY, player) {
- var dx = player.x - self.x;
- var dy = player.y - self.y;
- var distSqr = dx * dx + dy * dy;
- var updateCurve = (-Math.cos(++updateTick * Math.PI / updatePeriod) + 0.5) / 1.5;
- if (self.jumping) {
- if (updateCurve <= 0) {
- self.jumping = false;
- jumpVelocityX = 0;
- jumpVelocityY = 0;
+ if (!active) {
+ var dx = player.x - self.x;
+ var dy = player.y - self.y;
+ var distSqr = dx * dx + dy * dy;
+ if (distSqr <= activationDistSqr) {
+ active = true;
}
- } else {
- if (updateCurve > 0) {
- console.log(LK.ticks);
- var targetPosX = player.x + velocityX * jumpDuration;
- var targetPosY = player.y + velocityY * jumpDuration;
- var ddx = targetPosX - self.x;
- var ddy = targetPosY - self.y;
- var angle = Math.atan2(ddy, ddx);
- var targetDistSqr = ddx * ddx + ddy * ddy;
- var jumpSpeed = jumpSpeedMax * (targetDistSqr >= jumpDistMaxSqr ? 1 : Math.sqrt(targetDistSqr) / jumpDistMax);
- jumpVelocityX = Math.cos(angle) * jumpSpeed;
- jumpVelocityY = Math.sin(angle) * jumpSpeed;
- self.jumping = true;
+ }
+ if (active) {
+ var updateCurve = (-Math.cos(++updateTick * Math.PI / (updatePeriod / 2)) + 0.5) / 1.5;
+ if (self.jumping) {
+ if (updateCurve <= 0) {
+ self.jumping = false;
+ jumpVelocityX = 0;
+ jumpVelocityY = 0;
+ }
+ } else {
+ if (updateCurve > 0) {
+ var targetPosX = player.x + velocityX * jumpDuration;
+ var targetPosY = player.y + velocityY * jumpDuration;
+ var ddx = targetPosX - self.x;
+ var ddy = targetPosY - self.y;
+ var angle = Math.atan2(ddy, ddx);
+ var targetDistSqr = ddx * ddx + ddy * ddy;
+ var jumpSpeed = jumpSpeedMax * (targetDistSqr >= jumpDistMaxSqr ? 1 : Math.sqrt(targetDistSqr) / jumpDistMax);
+ jumpVelocityX = Math.cos(angle) * jumpSpeed;
+ jumpVelocityY = Math.sin(angle) * jumpSpeed;
+ self.jumping = true;
+ }
}
+ graphics.y = -Math.max(0, updateCurve) * jumpHeight;
+ graphics.scale.x = player.x < self.x ? -1 : 1;
+ graphics.scale.y = 1 + Math.min(0, updateCurve);
+ shadow.scale.set(1 - shadowReduction * updateCurve);
}
self.x += jumpVelocityX - velocityX;
self.y += jumpVelocityY - velocityY;
- graphics.y = -Math.max(0, updateCurve) * jumpHeight;
- graphics.scale.x = player.x < self.x ? -1 : 1;
- graphics.scale.y = 1 + Math.min(0, updateCurve);
- var shadowScale = 1 - shadowReduction * updateCurve;
- shadow.scale.set(shadowScale);
- return distSqr > despawnDistSqr;
+ return self.y < despawnY;
}
});
var Pickup = Container.expand(function (parent, x, y) {
var self = Container.call(this);
@@ -124,33 +132,28 @@
}
return distSqr <= collectDistSqr;
}
});
-var LandscapeTile = Container.expand(function (parent, x, y, args) {
+var LandscapeTile = Container.expand(function (parent, x, y, {lookup, xIndex, yIndex, width, height, density, pickups, monsters, player, key, landscapeTiles}) {
var self = Container.call(this);
parent.addChild(self);
self.x = x;
self.y = y;
- var landscapeTiles = args.landscapeTiles;
- var lookup = args.lookup;
- var xIndex = args.xIndex;
- var yIndex = args.yIndex;
- var width = args.width;
- var height = args.height;
- var density = args.density;
- var pickups = args.pickups;
- var key = args.key;
- self.checkCollision = checkCollision;
- self.activate = activate;
- self.width = width;
- self.height = height;
- self.active = false;
- self.key = key;
+ var pickupChance = 0.1;
+ var monsterChance = 0.01;
+ var distanceFactor = 10000;
+ var monsterDistance = 20000;
var obstructions = [];
var visual = self.createAsset('hitbox', 'Landscape area', 0.5, 0.5);
visual.alpha = 0;
visual.width = width;
visual.height = height;
+ self.activate = activate;
+ self.width = width;
+ self.height = height;
+ self.active = false;
+ self.key = key;
+ self.checkCollision = checkCollision;
function checkCollision(player) {
var reach = 100;
var dx = Math.abs(player.x - self.x);
var dy = Math.abs(player.y - self.y);
@@ -167,9 +170,9 @@
}
function activate() {
if (!self.active) {
self.active = true;
- var densityChance = Math.pow(1 + density, 3) / 100;
+ var densityChance = density * Math.random();
var obstructionTypes = ['largeTree', 'smallTree', 'smallTree', 'deadTree', 'smallRock', 'smallRock', 'largeRock', 'stump'];
var clearanceDist = 150;
var clearanceDistSqr = clearanceDist * clearanceDist;
var spawnBorder = 25;
@@ -177,96 +180,115 @@
var cols = Math.ceil(width / cellSize);
var rows = Math.ceil(height / cellSize);
var cellWidth = width / cols;
var cellHeight = height / rows;
- var cellInnerWidth = Math.max(0, cellWidth - 2 * spawnBorder);
- var cellInnerHeight = Math.max(0, cellHeight - 2 * spawnBorder);
var pickup;
if (Math.random() <= 0.1) {
- var pickupX = self.x - width / 2 + spawnBorder + Math.random() * (width - spawnBorder * 2);
- var pickupY = self.y - height / 2 + spawnBorder + Math.random() * (height - spawnBorder * 2);
- pickups.push(pickup = new Pickup(parent, pickupX, pickupY));
+ var {pointX, pointY} = randomPointInRect(self.x, self.y, width, height, clearanceDist);
+ pickups.push(pickup = new Pickup(parent, pointX, pointY));
}
+ if (player.distanceTravelled > monsterDistance && Math.random() <= monsterChance) {
+ var {pointX, pointY} = randomPointInRect(self.x, self.y, width, height, clearanceDist);
+ monsters.push(new Monster(parent, self.x, self.y));
+ }
for (i = 0; i < cols; i++) {
for (j = 0; j < rows; j++) {
if (Math.random() <= densityChance) {
var canPlace = true;
- var obsX = cellWidth * i + spawnBorder + Math.random() * cellInnerWidth - width / 2;
- var obsY = cellHeight * j + spawnBorder + Math.random() * cellInnerHeight - height / 2;
+ var {pointX, pointY} = randomPointInRect(cellWidth * i, cellHeight * j, cellWidth, cellHeight, spawnBorder);
if (pickup) {
- var dx = pickup.x - obsX;
- var dy = pickup.y - obsY;
+ var dx = pickup.x - pointX;
+ var dy = pickup.y - pointY;
var distSqr = dx * dx + dy * dy;
if (distSqr <= clearanceDistSqr) {
canPlace = false;
}
}
if (canPlace) {
var type = obstructionTypes[Math.floor(Math.random() * obstructionTypes.length)];
- obstructions.push(new Obstruction(self, obsX, obsY, type));
+ obstructions.push(new Obstruction(self, pointX, pointY, type));
}
}
}
}
}
var leftKey = xIndex - 1 + ':' + yIndex;
var rightKey = xIndex + 1 + ':' + yIndex;
var downKey = xIndex + ':' + (yIndex + 1);
+ var newDensity = (1 + Math.pow(Math.log(player.distanceTravelled / distanceFactor + 1), 2)) / 100;
if (!lookup[leftKey]) {
landscapeTiles.push(lookup[leftKey] = new LandscapeTile(parent, self.x - width, self.y, {
key: leftKey,
- density: Math.random(),
+ density: newDensity,
xIndex: xIndex - 1,
yIndex,
landscapeTiles,
width,
height,
lookup,
- pickups
+ pickups,
+ monsters,
+ player
}));
}
if (!lookup[rightKey]) {
landscapeTiles.push(lookup[rightKey] = new LandscapeTile(parent, self.x + width, self.y, {
key: rightKey,
- density: Math.random(),
+ density: newDensity,
xIndex: xIndex + 1,
yIndex,
landscapeTiles,
width,
height,
lookup,
- pickups
+ pickups,
+ monsters,
+ player
}));
}
if (!lookup[downKey]) {
landscapeTiles.push(lookup[downKey] = new LandscapeTile(parent, self.x, self.y + height, {
key: downKey,
- density: Math.random(),
+ density: newDensity,
yIndex: yIndex + 1,
xIndex,
landscapeTiles,
width,
height,
lookup,
- pickups
+ pickups,
+ monsters,
+ player
}));
}
+ function randomPointInRect(centerX, centerY, width, height, border = 0) {
+ var startX = centerX - width / 2 + border;
+ var startY = centerY - height / 2 + border;
+ var innerWidth = width - border * 2;
+ var innerHeight = height - border * 2;
+ var pointX = startX + Math.random() * innerWidth;
+ var pointY = startY + Math.random() * innerHeight;
+ return {
+ pointX,
+ pointY
+ };
+ }
}
});
var Obstruction = Container.expand(function (parent, x, y, type) {
var self = Container.call(this);
parent.addChild(self);
self.x = x;
self.y = y;
- self.active = true;
var graphics = self.createAsset(type, 'Obstruction graphics', 0.5, 1);
var hitbox = self.createAsset('hitbox', 'Obstruction hitbox', 0.5, 0.5);
var randomScale = 0.9 + Math.random() * 0.2;
hitbox.y = -25;
hitbox.alpha = 0;
hitbox.width = graphics.width * 0.8;
hitbox.height = graphics.width * 0.45;
self.scale.set(randomScale, randomScale);
+ self.active = true;
self.hitbox = hitbox;
self.deactivate = deactivate;
function deactivate() {
self.active = false;
@@ -277,21 +299,23 @@
var self = Container.call(this);
parent.addChild(self);
self.x = x;
self.y = y;
- self.update = update;
var speed = 0;
- self.invulnerable = false;
- self.invulnerableTime = 3 * 60;
- self.invulnerableTimer = 0;
+ var tiltSpeedFactor = 100;
var invulnerableReduction = 0.75;
var platformGraphics = self.createAsset('platform', 'Platform image', 0.4, 0.5);
var playerGraphics = self.createAsset('player', 'Player character', 0.575, 1);
var hitbox = self.createAsset('hitbox', 'Player Hitbox', 0.5, 0.5);
hitbox.width = 25;
hitbox.height = 25;
hitbox.alpha = 0;
+ self.invulnerable = false;
+ self.invulnerableTime = 3 * 60;
+ self.invulnerableTimer = 0;
+ self.distanceTravelled = 0;
self.hitbox = hitbox;
+ self.update = update;
function update(targetPosition) {
if (self.invulnerable) {
if (--self.invulnerableTimer <= 0) {
self.invulnerable = false;
@@ -301,15 +325,16 @@
var dx = targetPosition.x - self.x;
var dy = targetPosition.y - self.y;
var angle = angleClamp(Math.atan2(dy, dx));
var acceleration = (Math.sin(angle) - 0.1) * 2.0;
- speed = Math.max(0, speed * 0.95 + acceleration);
var reduction = self.invulnerable ? 1 - self.invulnerableTimer / self.invulnerableTime : 1;
- var velocityX = Math.cos(angle) * speed * reduction;
- var velocityY = Math.sin(angle) * speed * reduction;
+ speed = Math.max(0, speed * 0.95 + acceleration);
+ var velocityX = Math.cos(angle) * reduction * speed;
+ var velocityY = Math.sin(angle) * reduction * speed;
var facingSide = targetPosition.x < self.x ? -1 : 1;
+ self.distanceTravelled += speed;
platformGraphics.rotation = angle;
- playerGraphics.rotation = speed * reduction / 100 * (Math.PI / 2) * facingSide;
+ playerGraphics.rotation = speed * reduction / tiltSpeedFactor * (Math.PI / 2) * facingSide;
playerGraphics.scale.x = facingSide;
return {
velocityX,
velocityY
@@ -406,18 +431,15 @@
var tileSize = 512;
var playerPosX = Math.round(stageWidth / 2);
var playerPosY = Math.round(stageWidth / 3);
var tileMargin = tileSize;
- var monsterSpawnDistance = 5000;
- var monsterSpawnVariance = 2000;
var background = self.createAsset('background', 'Fullscreen background', 0, 0);
var landscapeLookup = {};
var landscapeTiles = [];
var pickups = [];
var monsters = [];
var effects = [];
var speed = 0;
- var monsterSpawn = monsterSpawnDistance + Math.random() * monsterSpawnVariance;
background.width = stageWidth;
background.height = stageHeight;
var interface = new Interface(self, 0, 10);
LK.gui.topCenter.addChild(interface);
@@ -431,9 +453,11 @@
xIndex: 0,
yIndex: 0,
key: '0:0',
landscapeTiles,
- pickups
+ monsters,
+ pickups,
+ player
}));
var isMouseDown = false;
var targetPosition = {
x: playerPosX,
@@ -453,15 +477,8 @@
});
LK.on('tick', function () {
var {velocityX, velocityY} = player.update(targetPosition);
trail.update(velocityX, velocityY);
- monsterSpawn -= velocityY;
- if (monsterSpawn < 0) {
- var monster = new Monster(self, playerPosX, stageHeight);
- monsters.push(monster);
- self.addChild(monster);
- monsterSpawn = monsterSpawnDistance + Math.random() * monsterSpawnVariance;
- }
for (var i = landscapeTiles.length - 1; i >= 0; i--) {
var landscapeTile = landscapeTiles[i];
landscapeTile.x -= velocityX;
landscapeTile.y -= velocityY;
Pixel art of a Santa. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a tree stump covered in snow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a dead tree covered in snow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a christmas tree covered in snow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a spruce tree covered in snow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a rock covered in snow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a christmas present counter. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a christmas present. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a blue christmas present. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Pixel art heart icon . Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
two vertical lines with a blank background.
pixel art of a large, snow covered rock . Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of skiis . Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a floating grinch monster . Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
single green firework explosion . Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a wooden board covered in snow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
pixel art of a wooden pole with snow at it's base. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
tileable white water texture pixel art.