User prompt
el sprite del slime sigue pegandose mucho al del player y se sobre posisiona sobre el la idea es que este un poco mas separado para que le haga daño y ese daño no sea continuo sino que hace dalo el enemigo en ticks de un segundo ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
ahora que los enemigos no se puedan atravezar ni estre ellos ni atravezar al player y solo con estar junto al player le van haciendo un 5% de daño
User prompt
muy bien pero ahora hay que darle mas velociad de movimiento
User prompt
muy bien ahora sabemos que el player se mueve de a media casilla pero cuando se mueve de forma constante se nota como no es fluido el movimiento asi que para hacerlo mas fluido podemos hacer que se mueva de a un quinto de casilla un 0.20
User prompt
ahora vamos a mejorar un poco la logca de los botones de las flechas y es que quiero que el personaje siga avanzando si el boton continua oprimido
User prompt
viendolo bien necesitamos otro asset para el player que sera el de mirar para abajo el cual va separado de el de mirar arriba y el delos lados como esta esta bien ya que es un mirrow pero arriba y abajo si distintos assets
User prompt
no asi no solo deja como el espacio para un sedundo asset del player y yo en ese aset pongo la imagen
User prompt
bien ya mira hacia los lados ahora falta arriba y abajo lo cual me imagino que tengo que yo poner la imagen pero tu agrega la logica para que yo al poner las imagenes el mire arriba y abajo
User prompt
ahora hay que mejorar un poco el personaje y es hacer que su sprite mire hacia el lado donde esta mirando o caminando asi tendra mas dinamismo
User prompt
muy bien soo un pequeño detalle los muros que no se generen entre celdas 1x1 sino que siempre esten dentro de un 1x1 relacionado al suelo
User prompt
muy bien soo un pequeño detalle los minerales y rocas que no se generen entre celdas 1x1 sino que siempre esten dentro de un 1x1 relacionado al suelo
User prompt
muy bien ahora mas mejoras visuales y es que como sabemos el mapa se compone de cuadriculas asi que quiero que todo ocupe 1x1 minerales personaje enemigos suelo y muros de manera visual ya que como estan las imagenes en los assets solo es ajustarlas
User prompt
todo muy bien ahora unos detalles en los botones ya que como le agrege imagenes a esos assets quiero que quites como esas flechas pico y espada blanquitos que estan encima de los botones y no dejan ver bien la imagen del boton
User prompt
necesitamos añadir textura en el suelo para poder ver mas claramente la cuadricula del mapa en general adeemas que el personaje asi como los enemigos que si lo hacen se pueda mover en un 1x1 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
perfecto ahora cambiemos un poco el aspecto de los minerales y rocas ya que deberian ocupar visualmente una casilla 1x1 cada una pero al minarlos reducen su tamaño visual a la mitad y se vuelve recolectable ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
muy bien y ahora en la parte derecha un boton de un pico y otro de espada el del pico al estar junto a un mineral o roca lo picara y el de espeda al estar unto a un enemigo le hara daño asi que los slimes deben ser derrotados con 3 golpes y dropear un item que sea slime
User prompt
en la parte inferior izquierda agregar una especie de botones que seran una flechas una hacia arriba otra hacia abajo una a la derecha y la otra a la izquierda y el personaje se movera en la direccion acorde cuando el player presione sobre una de esas flechas
User prompt
bien ahora un par de cambios los enemigos pueden pasar por pasillos de 1x1 pero el personaje no asi que eso tambien lo deberia hacer el personaje pasar por 1x1 ademas que con el click izquierdo si el personaje esta unto a un mineral o roca pueda minar dicho objeto
User prompt
has mas realista el sistema del mapa de las minas y que los enemicos no puedan atravezar las rocas ni minerales
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'addEventListener')' in or related to this line: 'document.addEventListener('keydown', handleKeyDown);' Line Number: 547
User prompt
nesesito hacer que el personaje lo pueda mover con awsd y al estar ensima de un objeto o enemigo interactue con el con la barra de espacio
User prompt
La lógica de los caminos es forma un camino único con tal vez varía difulcaciones no es crear salar ramdom en el mapa la idea es que se sienta como una mina de verdad
User prompt
Los muros deben formar el límite de cada piso formando caminos con lógica en los cuales el jugador se pueda desplazar y encontrar los minerales rojas y enemigos
User prompt
La roca también debe ser recolectable
User prompt
Porque todo tiene el mismo Sprite de las rocas al generar en cada piso de forma aletoria así mismo se deben generar los materiales con distintas áreas en probabilidades y los más raros aparecen con más frecuencia en pisos más altos
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var ActionButton = Container.expand(function (actionType) {
var self = Container.call(this);
self.actionType = actionType;
var buttonGraphics = self.attachAsset(actionType, {
anchorX: 0.5,
anchorY: 0.5
});
// Action image is now visible without text overlay
self.down = function (x, y, obj) {
// Visual feedback - make button slightly darker when pressed
buttonGraphics.tint = 0x666666;
if (self.actionType === 'pickaxe') {
// Mining action - check for adjacent rocks
for (var i = 0; i < rocks.length; i++) {
var rock = rocks[i];
if (!rock.destroyed) {
var dx = rock.x - player.x;
var dy = rock.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 80) {
rock.hit();
break; // Mine only one rock per click
}
}
}
} else if (self.actionType === 'sword') {
// Attack action - check for adjacent slimes
for (var i = 0; i < slimes.length; i++) {
var slime = slimes[i];
if (!slime.destroyed) {
var dx = slime.x - player.x;
var dy = slime.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 80 && hasLineOfSight(player.x, player.y, slime.x, slime.y)) {
slime.takeDamage(34); // 3 hits to kill (100/3 = ~34 damage)
LK.getSound('attack').play();
break; // Attack only one slime per click
}
}
}
}
};
self.up = function (x, y, obj) {
// Reset button color when released
buttonGraphics.tint = 0xFFFFFF;
};
return self;
});
var DirectionalButton = Container.expand(function (direction) {
var self = Container.call(this);
self.direction = direction;
var buttonGraphics = self.attachAsset('arrow' + direction.charAt(0).toUpperCase() + direction.slice(1), {
anchorX: 0.5,
anchorY: 0.5
});
// Arrow image is now visible without text overlay
self.down = function (x, y, obj) {
// Visual feedback - make button slightly darker when pressed
buttonGraphics.tint = 0x3A7BC8;
// Move player based on direction
var moveDistance = 32; // Move one grid cell
var newX = player.x;
var newY = player.y;
if (self.direction === 'Up') {
newY = player.y - moveDistance;
} else if (self.direction === 'Down') {
newY = player.y + moveDistance;
} else if (self.direction === 'Left') {
newX = player.x - moveDistance;
} else if (self.direction === 'Right') {
newX = player.x + moveDistance;
}
// Keep player within bounds
newX = Math.max(64, Math.min(1984, newX));
newY = Math.max(164, Math.min(2668, newY));
// Check collision before moving
if (!checkCollisionWithSolids(newX, newY, 15)) {
player.x = newX;
player.y = newY;
// Update player facing direction based on movement
if (self.direction === 'Left') {
player.setFacingDirection('left');
} else if (self.direction === 'Right') {
player.setFacingDirection('right');
}
}
};
self.up = function (x, y, obj) {
// Reset button color when released
buttonGraphics.tint = 0xFFFFFF;
};
return self;
});
var FloorTile = Container.expand(function () {
var self = Container.call(this);
var tileGraphics = self.attachAsset('floorTile', {
anchorX: 0.5,
anchorY: 0.5,
width: 64,
height: 64
});
// Add subtle border to show grid lines
tileGraphics.alpha = 0.3;
return self;
});
var HealthItem = Container.expand(function () {
var self = Container.call(this);
var heartGraphics = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5,
width: 32,
height: 32
});
self.collected = false;
self.healAmount = 25;
self.collect = function () {
if (self.collected) return;
self.collected = true;
LK.getSound('collect').play();
player.heal(self.healAmount);
// Remove from healthItems array
for (var i = healthItems.length - 1; i >= 0; i--) {
if (healthItems[i] === self) {
healthItems.splice(i, 1);
break;
}
}
game.removeChild(self);
};
return self;
});
var Ladder = Container.expand(function () {
var self = Container.call(this);
var ladderGraphics = self.attachAsset('ladder', {
anchorX: 0.5,
anchorY: 0.5,
width: 64,
height: 64
});
self.used = false;
self.use = function () {
if (self.used) return;
self.used = true;
currentFloor++;
generateFloor();
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
width: 64,
height: 64
});
self.maxHealth = 100;
self.health = self.maxHealth;
self.speed = 3;
self.attackRange = 80;
self.attackDamage = 25;
self.lastAttackTime = 0;
self.attackCooldown = 500;
self.facingDirection = 'right'; // Track which direction player is facing
self.lastX = 0; // Track last position to determine movement direction
self.lastY = 0;
// Method to update sprite direction based on facing
self.updateSpriteDirection = function () {
if (self.facingDirection === 'left') {
playerGraphics.scale.x = -1; // Flip sprite horizontally
} else {
playerGraphics.scale.x = 1; // Normal sprite orientation
}
};
// Method to set facing direction and update sprite
self.setFacingDirection = function (direction) {
if (direction === 'left' || direction === 'right') {
self.facingDirection = direction;
self.updateSpriteDirection();
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
}
LK.effects.flashObject(self, 0xFF0000, 300);
LK.getSound('hurt').play();
};
self.heal = function (amount) {
self.health = Math.min(self.maxHealth, self.health + amount);
};
self.canAttack = function () {
return LK.ticks - self.lastAttackTime > self.attackCooldown;
};
self.canMoveTo = function (x, y) {
return !checkCollisionWithSolids(x, y, 15);
};
self.update = function () {
// Detect movement direction and update facing
if (self.x !== self.lastX) {
if (self.x > self.lastX) {
self.setFacingDirection('right');
} else if (self.x < self.lastX) {
self.setFacingDirection('left');
}
}
// Update last position for next frame
self.lastX = self.x;
self.lastY = self.y;
};
self.attack = function () {
if (!self.canAttack()) return;
self.lastAttackTime = LK.ticks;
LK.getSound('attack').play();
// Check for slimes in attack range with line of sight
for (var i = 0; i < slimes.length; i++) {
var slime = slimes[i];
var dx = slime.x - self.x;
var dy = slime.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.attackRange && hasLineOfSight(self.x, self.y, slime.x, slime.y)) {
slime.takeDamage(self.attackDamage);
}
}
// Check for rocks in attack range with line of sight
for (var i = 0; i < rocks.length; i++) {
var rock = rocks[i];
var dx = rock.x - self.x;
var dy = rock.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.attackRange && hasLineOfSight(self.x, self.y, rock.x, rock.y)) {
rock.hit();
}
}
};
return self;
});
var Resource = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
self.collected = false;
var resourceGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5,
width: 32,
height: 32
});
self.collect = function () {
if (self.collected) return;
self.collected = true;
LK.getSound('collect').play();
// Update inventory
if (!inventory[self.type]) {
inventory[self.type] = 0;
}
inventory[self.type]++;
// Remove from resources array
for (var i = resources.length - 1; i >= 0; i--) {
if (resources[i] === self) {
resources.splice(i, 1);
break;
}
}
game.removeChild(self);
};
return self;
});
var Rock = Container.expand(function (rockType) {
var self = Container.call(this);
self.rockType = rockType || 'rock';
var rockGraphics = self.attachAsset(self.rockType, {
anchorX: 0.5,
anchorY: 0.5,
width: 64,
height: 64
});
self.maxHealth = 3;
self.health = self.maxHealth;
self.destroyed = false;
self.mined = false;
self.hit = function () {
if (self.destroyed) return;
self.health--;
LK.getSound('mine_hit').play();
LK.effects.flashObject(self, 0xFFFFFF, 200);
if (self.health <= 0) {
self.mine();
}
};
self.mine = function () {
if (self.mined || self.destroyed) return;
self.mined = true;
// Animate to half size and make collectable
tween(rockGraphics, {
width: 32,
height: 32
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Now it becomes a collectable resource
self.collectable = true;
}
});
};
self.destroy = function () {
if (self.destroyed) return;
self.destroyed = true;
// Drop resources based on rock type
var resource;
if (self.rockType === 'coal') {
resource = new Resource('coal');
} else if (self.rockType === 'copper_ore') {
resource = new Resource('copper_ore');
} else if (self.rockType === 'iron_ore') {
resource = new Resource('iron_ore');
} else if (self.rockType === 'gold_ore') {
resource = new Resource('gold_ore');
} else if (self.rockType === 'gem') {
resource = new Resource('gem');
} else {
// Regular rock always drops a rock resource
resource = new Resource('rock');
}
if (resource) {
resource.x = self.x;
resource.y = self.y;
resources.push(resource);
game.addChild(resource);
}
// Chance to spawn ladder if it doesn't exist yet
if (!ladder && Math.random() < 0.15) {
ladder = new Ladder();
ladder.x = self.x;
ladder.y = self.y;
game.addChild(ladder);
}
// Remove from rocks array
for (var i = rocks.length - 1; i >= 0; i--) {
if (rocks[i] === self) {
rocks.splice(i, 1);
break;
}
}
game.removeChild(self);
};
self.collect = function () {
if (!self.collectable || self.destroyed) return;
LK.getSound('collect').play();
// Update inventory
if (!inventory[self.rockType]) {
inventory[self.rockType] = 0;
}
inventory[self.rockType]++;
self.destroy();
};
return self;
});
var Slime = Container.expand(function () {
var self = Container.call(this);
var slimeGraphics = self.attachAsset('slime', {
anchorX: 0.5,
anchorY: 0.5,
width: 64,
height: 64
});
self.maxHealth = 3;
self.health = self.maxHealth;
self.speed = 1;
self.attackDamage = 15;
self.lastAttackTime = 0;
self.attackCooldown = 1000;
self.attackRange = 50;
self.destroyed = false;
self.takeDamage = function (damage) {
if (self.destroyed) return;
self.health -= damage;
LK.effects.flashObject(self, 0xFF0000, 200);
if (self.health <= 0) {
self.destroy();
}
};
self.destroy = function () {
if (self.destroyed) return;
self.destroyed = true;
// Always drop slime item
var slimeResource = new Resource('slime');
slimeResource.x = self.x;
slimeResource.y = self.y;
resources.push(slimeResource);
game.addChild(slimeResource);
// Drop heart sometimes
if (Math.random() < 0.3) {
var heart = new HealthItem();
heart.x = self.x;
heart.y = self.y;
healthItems.push(heart);
game.addChild(heart);
}
// Remove from slimes array
for (var i = slimes.length - 1; i >= 0; i--) {
if (slimes[i] === self) {
slimes.splice(i, 1);
break;
}
}
// Increase score
LK.setScore(LK.getScore() + 10);
game.removeChild(self);
};
self.update = function () {
if (self.destroyed) return;
// Check if player is visible (line of sight)
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (hasLineOfSight(self.x, self.y, player.x, player.y) && distance < 300) {
// Move towards player if visible and within detection range
if (distance > 0) {
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
var newX = self.x + moveX;
var newY = self.y + moveY;
// Check collision before moving
if (!checkCollisionWithSolids(newX, newY, 15)) {
self.x = newX;
self.y = newY;
}
}
// Attack player if in range and visible
if (distance <= self.attackRange && LK.ticks - self.lastAttackTime > self.attackCooldown) {
self.lastAttackTime = LK.ticks;
player.takeDamage(self.attackDamage);
}
}
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
width: 64,
height: 64
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2F1B14
});
/****
* Game Code
****/
var player;
var rocks = [];
var slimes = [];
var resources = [];
var healthItems = [];
var ladder;
var inventory = {};
var currentFloor = 1;
var walls = [];
var floorTiles = [];
function checkCollisionWithWalls(x, y, radius) {
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
var dx = Math.abs(x - wall.x);
var dy = Math.abs(y - wall.y);
if (dx < 32 + radius && dy < 32 + radius) {
return true;
}
}
return false;
}
function checkCollisionWithSolids(x, y, radius) {
// Check collision with walls
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
var dx = Math.abs(x - wall.x);
var dy = Math.abs(y - wall.y);
if (dx < 32 + radius && dy < 32 + radius) {
return true;
}
}
// Check collision with rocks
for (var i = 0; i < rocks.length; i++) {
var rock = rocks[i];
if (!rock.destroyed && !rock.mined) {
var dx = Math.abs(x - rock.x);
var dy = Math.abs(y - rock.y);
if (dx < 16 + radius && dy < 16 + radius) {
return true;
}
}
}
return false;
}
function hasLineOfSight(x1, y1, x2, y2) {
var dx = x2 - x1;
var dy = y2 - y1;
var distance = Math.sqrt(dx * dx + dy * dy);
var steps = Math.floor(distance / 16);
for (var i = 0; i <= steps; i++) {
var checkX = x1 + dx * i / steps;
var checkY = y1 + dy * i / steps;
if (checkCollisionWithSolids(checkX, checkY, 8)) {
return false;
}
}
return true;
}
// UI Elements
var healthBar;
var floorText;
var inventoryText;
function initializeGame() {
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
// Initialize position tracking
player.lastX = player.x;
player.lastY = player.y;
// Create UI
healthBar = new Text2('Health: 100/100', {
size: 40,
fill: 0xFF0000
});
healthBar.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthBar);
healthBar.x = 120;
healthBar.y = 20;
floorText = new Text2('Floor: 1', {
size: 40,
fill: 0xFFFFFF
});
floorText.anchor.set(0.5, 0);
LK.gui.top.addChild(floorText);
floorText.y = 20;
inventoryText = new Text2('', {
size: 30,
fill: 0xFFFF00
});
inventoryText.anchor.set(1, 0);
LK.gui.topRight.addChild(inventoryText);
inventoryText.x = -20;
inventoryText.y = 20;
generateFloor();
// Create directional control buttons in bottom left
var buttonSize = 80;
var buttonSpacing = 90;
var baseX = 120;
var baseY = -200;
// Create up arrow button
var upButton = new DirectionalButton('Up');
upButton.x = baseX;
upButton.y = baseY - buttonSpacing;
LK.gui.bottomLeft.addChild(upButton);
// Create down arrow button
var downButton = new DirectionalButton('Down');
downButton.x = baseX;
downButton.y = baseY + buttonSpacing;
LK.gui.bottomLeft.addChild(downButton);
// Create left arrow button
var leftButton = new DirectionalButton('Left');
leftButton.x = baseX - buttonSpacing;
leftButton.y = baseY;
LK.gui.bottomLeft.addChild(leftButton);
// Create right arrow button
var rightButton = new DirectionalButton('Right');
rightButton.x = baseX + buttonSpacing;
rightButton.y = baseY;
LK.gui.bottomLeft.addChild(rightButton);
// Create action buttons on the right side
var actionBaseX = -120;
var actionBaseY = -200;
// Create pickaxe button
var pickaxeButton = new ActionButton('pickaxe');
pickaxeButton.x = actionBaseX;
pickaxeButton.y = actionBaseY - buttonSpacing / 2;
LK.gui.bottomRight.addChild(pickaxeButton);
// Create sword button
var swordButton = new ActionButton('sword');
swordButton.x = actionBaseX;
swordButton.y = actionBaseY + buttonSpacing / 2;
LK.gui.bottomRight.addChild(swordButton);
}
function generateFloor() {
// Clear existing objects
clearFloor();
// Generate floor tiles for grid visualization
for (var x = 64; x < 2048; x += 64) {
for (var y = 196; y < 2700; y += 64) {
var floorTile = new FloorTile();
floorTile.x = x;
floorTile.y = y;
floorTiles.push(floorTile);
game.addChild(floorTile);
}
}
// Generate perimeter walls
for (var x = 0; x < 2048; x += 64) {
var topWall = new Wall();
topWall.x = x + 32;
topWall.y = 132;
walls.push(topWall);
game.addChild(topWall);
var bottomWall = new Wall();
bottomWall.x = x + 32;
bottomWall.y = 2700;
walls.push(bottomWall);
game.addChild(bottomWall);
}
for (var y = 132; y < 2700; y += 64) {
var leftWall = new Wall();
leftWall.x = 32;
leftWall.y = y + 32;
walls.push(leftWall);
game.addChild(leftWall);
var rightWall = new Wall();
rightWall.x = 2016;
rightWall.y = y + 32;
walls.push(rightWall);
game.addChild(rightWall);
}
// Generate structured maze with corridors and chambers
generateMazeStructure();
// Generate rocks with different types based on floor, placed in accessible areas
var numRocks = 15 + Math.floor(currentFloor * 2);
for (var i = 0; i < numRocks; i++) {
var rockType = 'rock'; // Default rock type
var rand = Math.random();
// Higher floors have better chances for rare materials
var floorMultiplier = Math.min(currentFloor / 10, 1); // Cap at floor 10
if (rand < 0.3) {
rockType = 'coal'; // Common on all floors
} else if (rand < 0.3 + 0.2 * floorMultiplier) {
rockType = 'copper_ore'; // More common on higher floors
} else if (rand < 0.3 + 0.2 * floorMultiplier + 0.15 * floorMultiplier) {
rockType = 'iron_ore'; // Rare, more common on higher floors
} else if (rand < 0.3 + 0.2 * floorMultiplier + 0.15 * floorMultiplier + 0.1 * floorMultiplier) {
rockType = 'gold_ore'; // Very rare, much more common on higher floors
} else if (rand < 0.3 + 0.2 * floorMultiplier + 0.15 * floorMultiplier + 0.1 * floorMultiplier + 0.05 * floorMultiplier) {
rockType = 'gem'; // Extremely rare, only on higher floors
}
var rock = new Rock(rockType);
var attempts = 0;
do {
// Generate grid-aligned positions (64x64 grid cells)
var gridX = Math.floor(Math.random() * 26) + 3; // Grid positions 3-28
var gridY = Math.floor(Math.random() * 32) + 5; // Grid positions 5-36
rock.x = 64 + gridX * 64; // Center in grid cell
rock.y = 196 + gridY * 64; // Center in grid cell
attempts++;
} while (checkCollisionWithSolids(rock.x, rock.y, 24) && attempts < 100);
// If we couldn't find a good spot after 100 attempts, place it along corridors
if (attempts >= 100) {
var corridorGridX = Math.floor(Math.random() * 18) + 6; // Corridor area grid
var corridorGridY = Math.floor(Math.random() * 20) + 9; // Corridor area grid
rock.x = 64 + corridorGridX * 64;
rock.y = 196 + corridorGridY * 64;
// Try a few more times in corridor area
var corridorAttempts = 0;
while (checkCollisionWithSolids(rock.x, rock.y, 24) && corridorAttempts < 20) {
corridorGridX = Math.floor(Math.random() * 18) + 6;
corridorGridY = Math.floor(Math.random() * 20) + 9;
rock.x = 64 + corridorGridX * 64;
rock.y = 196 + corridorGridY * 64;
corridorAttempts++;
}
}
rocks.push(rock);
game.addChild(rock);
}
// Generate slimes in accessible areas
var numSlimes = 3 + Math.floor(currentFloor * 1.5);
for (var i = 0; i < numSlimes; i++) {
var slime = new Slime();
var attempts = 0;
do {
slime.x = 200 + Math.random() * 1648;
slime.y = 300 + Math.random() * 2132;
attempts++;
} while (checkCollisionWithSolids(slime.x, slime.y, 20) && attempts < 100);
// If we couldn't find a good spot after 100 attempts, place it along corridors
if (attempts >= 100) {
slime.x = 400 + Math.random() * 1200;
slime.y = 600 + Math.random() * 1400;
// Try a few more times in corridor area
var corridorAttempts = 0;
while (checkCollisionWithSolids(slime.x, slime.y, 20) && corridorAttempts < 20) {
slime.x = 400 + Math.random() * 1200;
slime.y = 600 + Math.random() * 1400;
corridorAttempts++;
}
}
slime.maxHealth += Math.floor(currentFloor * 10);
slime.health = slime.maxHealth;
slimes.push(slime);
game.addChild(slime);
}
// Ladder will be generated when mining rocks
ladder = null;
// Update floor text
floorText.setText('Floor: ' + currentFloor);
}
function clearFloor() {
// Remove all floor tiles
for (var i = 0; i < floorTiles.length; i++) {
game.removeChild(floorTiles[i]);
}
floorTiles = [];
// Remove all walls
for (var i = 0; i < walls.length; i++) {
game.removeChild(walls[i]);
}
walls = [];
// Remove all rocks
for (var i = 0; i < rocks.length; i++) {
game.removeChild(rocks[i]);
}
rocks = [];
// Remove all slimes
for (var i = 0; i < slimes.length; i++) {
game.removeChild(slimes[i]);
}
slimes = [];
// Remove all resources
for (var i = 0; i < resources.length; i++) {
game.removeChild(resources[i]);
}
resources = [];
// Remove all health items
for (var i = 0; i < healthItems.length; i++) {
game.removeChild(healthItems[i]);
}
healthItems = [];
// Remove ladder
if (ladder) {
game.removeChild(ladder);
ladder = null;
}
}
function updateUI() {
// Update health bar
healthBar.setText('Health: ' + player.health + '/' + player.maxHealth);
// Update inventory display
var inventoryStr = '';
for (var item in inventory) {
if (inventory[item] > 0) {
inventoryStr += item.replace('_', ' ') + ': ' + inventory[item] + '\n';
}
}
inventoryText.setText(inventoryStr);
}
var dragNode = null;
function handleMove(x, y, obj) {
if (dragNode) {
var newX = x;
var newY = y;
// Keep player within bounds
newX = Math.max(64, Math.min(1984, newX));
newY = Math.max(164, Math.min(2668, newY));
// Check collision with walls and rocks
if (!checkCollisionWithSolids(newX, newY, 15)) {
var oldX = dragNode.x;
dragNode.x = newX;
dragNode.y = newY;
// Update player facing direction based on drag movement
if (dragNode === player && newX !== oldX) {
if (newX > oldX) {
player.setFacingDirection('right');
} else if (newX < oldX) {
player.setFacingDirection('left');
}
}
}
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = player;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
if (!player) return;
// Update player
player.update();
// Update slimes
for (var i = 0; i < slimes.length; i++) {
slimes[i].update();
}
// Automatic mining removed - now controlled by left click
// Check resource collection
for (var i = resources.length - 1; i >= 0; i--) {
var resource = resources[i];
var dx = resource.x - player.x;
var dy = resource.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 40) {
resource.collect();
}
}
// Check mined rock collection
for (var i = rocks.length - 1; i >= 0; i--) {
var rock = rocks[i];
if (rock.collectable && !rock.destroyed) {
var dx = rock.x - player.x;
var dy = rock.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 40) {
rock.collect();
}
}
}
// Check health item collection
for (var i = healthItems.length - 1; i >= 0; i--) {
var healthItem = healthItems[i];
var dx = healthItem.x - player.x;
var dy = healthItem.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 40) {
healthItem.collect();
}
}
// Check ladder interaction
if (ladder && !ladder.used) {
var dx = ladder.x - player.x;
var dy = ladder.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 50) {
ladder.use();
}
}
// Update UI
updateUI();
};
// Initialize the game
initializeGame();
function generateMazeStructure() {
// Create grid for maze generation (30x38 cells, each cell is 64x64 pixels)
var gridWidth = 30;
var gridHeight = 38;
var cellSize = 64;
var startX = 96;
var startY = 196;
// Create a grid to track where corridors are
var corridorGrid = [];
for (var x = 0; x < gridWidth; x++) {
corridorGrid[x] = [];
for (var y = 0; y < gridHeight; y++) {
corridorGrid[x][y] = false;
}
}
// Create main entrance tunnel from top-center
var entranceX = Math.floor(gridWidth / 2);
for (var y = 2; y < 8; y++) {
corridorGrid[entranceX][y] = true;
// Make entrance wider (3 tiles wide)
if (entranceX - 1 >= 0) corridorGrid[entranceX - 1][y] = true;
if (entranceX + 1 < gridWidth) corridorGrid[entranceX + 1][y] = true;
}
// Create main horizontal distribution corridor
var mainCorridorY = 8;
for (var x = 4; x < gridWidth - 4; x++) {
corridorGrid[x][mainCorridorY] = true;
// Make main corridor wider
corridorGrid[x][mainCorridorY + 1] = true;
}
// Create realistic mining tunnels branching from main corridor
var numMainTunnels = 4 + Math.floor(currentFloor / 3);
var tunnelSpacing = Math.floor((gridWidth - 8) / numMainTunnels);
for (var i = 0; i < numMainTunnels; i++) {
var tunnelX = 4 + i * tunnelSpacing + Math.floor(Math.random() * (tunnelSpacing / 2));
var tunnelLength = 8 + Math.floor(Math.random() * 12);
var tunnelStartY = mainCorridorY + 2;
// Create main mining tunnel going down
for (var y = tunnelStartY; y < Math.min(tunnelStartY + tunnelLength, gridHeight - 2); y++) {
corridorGrid[tunnelX][y] = true;
// Add slight width variation to make it more natural
if (Math.random() > 0.6) {
if (tunnelX - 1 >= 2) corridorGrid[tunnelX - 1][y] = true;
} else if (Math.random() > 0.6) {
if (tunnelX + 1 < gridWidth - 2) corridorGrid[tunnelX + 1][y] = true;
}
}
// Create mining chambers at the end of tunnels
if (tunnelStartY + tunnelLength < gridHeight - 4) {
var chamberY = tunnelStartY + tunnelLength - 2;
var chamberSize = 2 + Math.floor(Math.random() * 2); // 2x2 or 3x3 chamber
for (var cx = -chamberSize; cx <= chamberSize; cx++) {
for (var cy = -1; cy <= chamberSize; cy++) {
var newX = tunnelX + cx;
var newY = chamberY + cy;
if (newX >= 2 && newX < gridWidth - 2 && newY >= 2 && newY < gridHeight - 2) {
corridorGrid[newX][newY] = true;
}
}
}
}
// Create side branches from main tunnels (like real mine shafts)
var numSideBranches = 1 + Math.floor(Math.random() * 2);
for (var j = 0; j < numSideBranches; j++) {
var branchY = tunnelStartY + 3 + Math.floor(Math.random() * (tunnelLength - 6));
var branchDirection = Math.random() > 0.5 ? 1 : -1;
var branchLength = 3 + Math.floor(Math.random() * 5);
for (var k = 1; k <= branchLength; k++) {
var branchX = tunnelX + k * branchDirection;
if (branchX >= 2 && branchX < gridWidth - 2) {
corridorGrid[branchX][branchY] = true;
// Small chamber at end of side branch
if (k === branchLength) {
if (branchY - 1 >= 2) corridorGrid[branchX][branchY - 1] = true;
if (branchY + 1 < gridHeight - 2) corridorGrid[branchX][branchY + 1] = true;
}
}
}
}
}
// Create connecting tunnels between some main tunnels (crosscuts)
var numConnections = Math.floor(numMainTunnels / 2);
for (var i = 0; i < numConnections; i++) {
var connectionY = mainCorridorY + 5 + Math.floor(Math.random() * 10);
var startX = 4 + Math.floor(Math.random() * (gridWidth - 12));
var endX = startX + 4 + Math.floor(Math.random() * 6);
for (var x = startX; x <= Math.min(endX, gridWidth - 3); x++) {
if (connectionY >= 2 && connectionY < gridHeight - 2) {
corridorGrid[x][connectionY] = true;
}
}
}
// Convert corridor grid to walls (fill in non-corridor spaces)
for (var x = 2; x < gridWidth - 2; x++) {
for (var y = 2; y < gridHeight - 2; y++) {
if (!corridorGrid[x][y]) {
var wall = new Wall();
// Align wall to grid cell center (64x64 grid cells)
wall.x = 64 + x * cellSize; // Center in grid cell
wall.y = 196 + y * cellSize; // Center in grid cell
walls.push(wall);
game.addChild(wall);
}
}
}
// Add structural support pillars in wider areas
var numPillars = Math.floor(currentFloor / 3);
for (var i = 0; i < numPillars; i++) {
var pillarX = Math.floor(6 + Math.random() * (gridWidth - 12));
var pillarY = Math.floor(mainCorridorY + 3 + Math.random() * (gridHeight - mainCorridorY - 6));
// Only place pillar if it's in a corridor and won't block paths
if (corridorGrid[pillarX][pillarY]) {
var canPlace = true;
// Check if placing pillar would block critical paths
for (var dx = -1; dx <= 1 && canPlace; dx++) {
for (var dy = -1; dy <= 1 && canPlace; dy++) {
var checkX = pillarX + dx;
var checkY = pillarY + dy;
if (checkX >= 0 && checkX < gridWidth && checkY >= 0 && checkY < gridHeight) {
// Don't place if it would create a dead end
if (!corridorGrid[checkX][checkY] && (dx === 0 || dy === 0)) {
var adjacentCorridors = 0;
if (checkX > 0 && corridorGrid[checkX - 1][checkY]) adjacentCorridors++;
if (checkX < gridWidth - 1 && corridorGrid[checkX + 1][checkY]) adjacentCorridors++;
if (checkY > 0 && corridorGrid[checkX][checkY - 1]) adjacentCorridors++;
if (checkY < gridHeight - 1 && corridorGrid[checkX][checkY + 1]) adjacentCorridors++;
if (adjacentCorridors < 2) canPlace = false;
}
}
}
}
if (canPlace && Math.random() > 0.3) {
var wall = new Wall();
// Align pillar wall to grid cell center (64x64 grid cells)
wall.x = 64 + pillarX * cellSize; // Center in grid cell
wall.y = 196 + pillarY * cellSize; // Center in grid cell
walls.push(wall);
game.addChild(wall);
}
}
}
} ===================================================================
--- original.js
+++ change.js
@@ -84,8 +84,14 @@
// Check collision before moving
if (!checkCollisionWithSolids(newX, newY, 15)) {
player.x = newX;
player.y = newY;
+ // Update player facing direction based on movement
+ if (self.direction === 'Left') {
+ player.setFacingDirection('left');
+ } else if (self.direction === 'Right') {
+ player.setFacingDirection('right');
+ }
}
};
self.up = function (x, y, obj) {
// Reset button color when released
@@ -162,8 +168,26 @@
self.attackRange = 80;
self.attackDamage = 25;
self.lastAttackTime = 0;
self.attackCooldown = 500;
+ self.facingDirection = 'right'; // Track which direction player is facing
+ self.lastX = 0; // Track last position to determine movement direction
+ self.lastY = 0;
+ // Method to update sprite direction based on facing
+ self.updateSpriteDirection = function () {
+ if (self.facingDirection === 'left') {
+ playerGraphics.scale.x = -1; // Flip sprite horizontally
+ } else {
+ playerGraphics.scale.x = 1; // Normal sprite orientation
+ }
+ };
+ // Method to set facing direction and update sprite
+ self.setFacingDirection = function (direction) {
+ if (direction === 'left' || direction === 'right') {
+ self.facingDirection = direction;
+ self.updateSpriteDirection();
+ }
+ };
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
@@ -180,8 +204,21 @@
};
self.canMoveTo = function (x, y) {
return !checkCollisionWithSolids(x, y, 15);
};
+ self.update = function () {
+ // Detect movement direction and update facing
+ if (self.x !== self.lastX) {
+ if (self.x > self.lastX) {
+ self.setFacingDirection('right');
+ } else if (self.x < self.lastX) {
+ self.setFacingDirection('left');
+ }
+ }
+ // Update last position for next frame
+ self.lastX = self.x;
+ self.lastY = self.y;
+ };
self.attack = function () {
if (!self.canAttack()) return;
self.lastAttackTime = LK.ticks;
LK.getSound('attack').play();
@@ -495,8 +532,11 @@
function initializeGame() {
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
+ // Initialize position tracking
+ player.lastX = player.x;
+ player.lastY = player.y;
// Create UI
healthBar = new Text2('Health: 100/100', {
size: 40,
fill: 0xFF0000
@@ -737,10 +777,19 @@
newX = Math.max(64, Math.min(1984, newX));
newY = Math.max(164, Math.min(2668, newY));
// Check collision with walls and rocks
if (!checkCollisionWithSolids(newX, newY, 15)) {
+ var oldX = dragNode.x;
dragNode.x = newX;
dragNode.y = newY;
+ // Update player facing direction based on drag movement
+ if (dragNode === player && newX !== oldX) {
+ if (newX > oldX) {
+ player.setFacingDirection('right');
+ } else if (newX < oldX) {
+ player.setFacingDirection('left');
+ }
+ }
}
}
}
game.move = handleMove;
@@ -752,8 +801,10 @@
dragNode = null;
};
game.update = function () {
if (!player) return;
+ // Update player
+ player.update();
// Update slimes
for (var i = 0; i < slimes.length; i++) {
slimes[i].update();
}
Heart pixart. In-Game asset. 2d. High contrast. No shadows
Muro de piedras tipo cueva. In-Game asset. 2d. High contrast. No shadows
Slime pixart cute. In-Game asset. 2d. High contrast. No shadows
Minero pixart cute. In-Game asset. 2d. High contrast. No shadows
Escalera pixart. In-Game asset. 2d. High contrast. No shadows
Gold ore poxart. In-Game asset. 2d. High contrast. No shadows
Coal ore. In-Game asset. 2d. High contrast. No shadows
Chopper ore pixart. In-Game asset. 2d. High contrast. No shadows
Rocas pixart. In-Game asset. 2d. High contrast. No shadows
Iron ore pixart. In-Game asset. 2d. High contrast. No shadows
Gema de mina super especial pixart. In-Game asset. 2d. High contrast. No shadows
flechita hacia arriba pixart. In-Game asset. 2d. High contrast. No shadows
pico de madera pixart. In-Game asset. 2d. High contrast. No shadows
espada de madera pixart. In-Game asset. 2d. High contrast. No shadows
quitale el circulo del casco
que el minero este mirando de frente y llendo de frente
suelo de tierra pixart. In-Game asset. 2d. High contrast. No shadows
boton de un inventario pixelart. In-Game asset. 2d. High contrast. No shadows
quitar la palabra "inventory"
entrada a una mina pixelart. In-Game asset. 2d. High contrast. No shadows
lobo babeando pixelart. In-Game asset. 2d. High contrast. No shadows
arbusto pixelart. In-Game asset. 2d. High contrast. No shadows
cesped pixelart. In-Game asset. 2d. High contrast. No shadows
npc market pixelart. In-Game asset. 2d. High contrast. No shadows
coin pixelart. In-Game asset. 2d. High contrast. No shadows