User prompt
Еще чуть чуть
User prompt
Чуть чуть в право
User prompt
Перемести предедущию точку гораздо левее
User prompt
Добавь слева почти в притык еще одну точку спавна патронов
User prompt
Еще на 2
User prompt
Еще на пиксель влево
User prompt
Еще на 1 пиксель в лево точку спавна пуль
User prompt
Перемести чуть чуть ближе к кораблю
User prompt
Еще совсем капельку в лево
User prompt
Еще чуть чуть в лево
User prompt
Перемести в лево
User prompt
Смести её на место предыдущей точки
User prompt
Удали правую точку выпуска снарядов
User prompt
В лево на пиксель
User prompt
На половину пиксела в право
User prompt
Еще на 1
User prompt
Еще на 25
User prompt
Перемести точку справа встрелело на 25 пикселей
User prompt
Еще левее
User prompt
Перемести точку справа снарядов в лево
User prompt
Перемести снаряды в лево
User prompt
Перемести сильно в лево снаряды
User prompt
Перемести сильно в лево
User prompt
Перемести снаряд в точку носа корабля
User prompt
Сделай так чтоб корабль стрелял туда куда смотрит
/****
* Classes
****/
// EnemyShip Class: Represents an enemy spacecraft.
var EnemyShip = Container.expand(function () {
var self = Container.call(this);
self.attachAsset('enemyShipSprite', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4; // Pixels per frame, moving downwards. Can be varied for difficulty.
// Called automatically by LK engine if the instance is added to the game stage.
self.update = function () {
self.y += self.speed;
};
return self;
});
// For when the player's ship is destroyed
// No plugins are explicitly required for this MVP of Starship Onslaught.
// Joystick Class: Handles touch input for player movement.
var Joystick = Container.expand(function (params) {
var self = Container.call(this);
params = params || {};
self.base = self.attachAsset('joystickBaseSprite', {
anchorX: 0.5,
anchorY: 0.5
});
self.knob = self.attachAsset('joystickKnobSprite', {
anchorX: 0.5,
anchorY: 0.5
});
// Calculate radius: if params.radius is provided, use it. Otherwise, calculate based on asset sizes.
// This makes the knob's travel area fit within the base.
self.radius = params.radius !== undefined ? params.radius : (self.base.width - self.knob.width) / 2;
self.active = false;
self.knobXNormalized = 0; // Normalized displacement (-1 to 1)
self.knobYNormalized = 0; // Normalized displacement (-1 to 1)
// Method called when a touch starts, joystick moves to this position
self.onDown = function (globalX, globalY) {
// event param removed, x/y renamed for clarity
// Position the joystick's center at the touch point.
// (self.x, self.y refers to the Joystick container's center based on asset setup)
self.x = globalX;
self.y = globalY;
self.active = true;
// The touch is at the new center of the joystick.
// The knob should be centered on the base initially.
self.resetKnob(); // This sets knob local x/y to 0 and normalized displacement to 0.
// No return value needed as game.down will assume joystick is now the dragNode.
};
// Method called when the touch moves while joystick is active
self.onMove = function (x, y, event) {
if (!self.active) return;
var localPos = self.toLocal({
x: x,
y: y
});
self.updateKnobPosition(localPos.x, localPos.y);
};
// Method called when the touch is released
self.onUp = function () {
if (!self.active) return;
self.active = false;
self.resetKnob();
};
// Internal method to update the knob's visual position and normalized displacement
self.updateKnobPosition = function (localX, localY) {
var angle = Math.atan2(localY, localX);
var distance = Math.sqrt(localX * localX + localY * localY);
// Clamp knob movement to the defined radius
var clampedDistance = Math.min(distance, self.radius);
self.knob.x = Math.cos(angle) * clampedDistance;
self.knob.y = Math.sin(angle) * clampedDistance;
// Store normalized displacement if radius is greater than zero
if (self.radius > 0) {
self.knobXNormalized = self.knob.x / self.radius;
self.knobYNormalized = self.knob.y / self.radius;
} else {
self.knobXNormalized = 0;
self.knobYNormalized = 0;
}
};
// Resets the knob to the center and clears displacement
self.resetKnob = function () {
self.knob.x = 0;
self.knob.y = 0;
self.knobXNormalized = 0;
self.knobYNormalized = 0;
};
// Returns the current normalized displacement vector
self.getDisplacement = function () {
// Return zero displacement if not active, to prevent unwanted movement
// when touch is released but game loop queries displacement before onUp is fully processed.
if (!self.active) {
return {
dx: 0,
dy: 0
};
}
return {
dx: self.knobXNormalized,
dy: self.knobYNormalized
};
};
// Initialize knob position
self.resetKnob();
return self;
});
// PlayerBullet Class: Represents bullets fired by the player.
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
self.attachAsset('playerBulletSprite', {
anchorX: 0.5,
anchorY: 0.5
});
// Default speed (pixels per frame)
self.speed = 30;
// Direction vector (set on spawn)
self.direction = {
dx: 0,
dy: -1
}; // Default: up
// Called automatically by LK engine.
self.update = function () {
// Move in the direction set at spawn
self.x += self.direction.dx * self.speed;
self.y += self.direction.dy * self.speed;
};
return self;
});
// PlayerShip Class: Represents the player's controllable starship.
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
// Attach the visual asset for the player's ship.
// The asset is anchored by its center within the container.
// The container's (self) x,y coordinates remain its top-left.
self.attachAsset('playerShipSprite', {
anchorX: 0.5,
anchorY: 0.5
// The graphic's local position is set to be the center of the container,
// assuming the container's width/height match the sprite's dimensions.
// This is implicitly handled if the container sizes to its children.
// For an 80x100 sprite, this places its center at container's (40,50).
// However, standard behavior for attachAsset might be that the child is added at (0,0) locally,
// and anchorX/Y refers to the texture anchor. So the visual sprite is centered around (0,0) of PlayerShip's local space.
// The container will automatically size based on its children. If the sprite is 80x100,
// centered at local (0,0), its bounds are -40 to +40 (x) and -50 to +50 (y).
// This means player.width and player.height would be 80 and 100, and player.x/y refers to its visual center.
// Let's stick to LK example: anchorX/Y for the *asset*, container x/y is top-left.
// The asset child will be added at (0,0) in container space. If its own anchor is 0.5,0.5,
// its visual center is at its (0,0) local position.
// The container's width/height will be that of the asset.
// Thus, player.x, player.y means the top-left of the bounding box of the player ship.
});
// Player movement and shooting are handled in the main game logic.
return self;
});
/****
* Initialize Game
****/
// Create the game instance with a dark space-like background.
var game = new LK.Game({
backgroundColor: 0x0A0A20 // Dark blue, almost black
});
/****
* Game Code
****/
// Define game-wide constants
// Initialize assets used in this game.
// Player's starship
// Enemy spacecraft
// Player's bullets
// Sound effects
var PLAYER_SHOOT_INTERVAL_TICKS = 25; // Player shoots roughly every 0.4 seconds (60/25)
var ENEMY_SPAWN_INTERVAL_TICKS = 75; // New enemy spawns roughly every 1.25 seconds (60/75)
var PLAYER_MOVE_SPEED = 8; // Speed of the player ship when controlled by joystick
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// Declare game state variables
var player;
var enemies = [];
var playerBullets = [];
var scoreTxt;
var joystick; // Variable for the joystick controller
var dragNode = null; // To keep track of the active draggable object (joystick or other elements if any)
// Initialize and display the score
scoreTxt = new Text2('Score: 0', {
// Added "Score: " prefix for clarity
size: 80,
// Readable size for mobile
fill: 0xE0E0E0 // Light gray for score text
});
scoreTxt.anchor.set(0.5, 0); // Anchor to the horizontal center and vertical top of the text
// Position score display at the top-center of the GUI layer
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 30; // Provide some padding from the very top edge, clear of potential top-left menu icon
// Create and position the player's ship
player = new PlayerShip();
game.addChild(player);
// Set initial position: horizontally centered, towards the bottom of the screen.
// player.width/height are dimensions of the PlayerShip container, derived from its sprite.
// player.x, player.y refers to the top-left corner of the player ship container.
player.x = (GAME_WIDTH - player.width) / 2;
player.y = GAME_HEIGHT - player.height - 250; // Initial position higher up, joystick will be at bottom
// Create and position the joystick
// The Joystick class calculates its own default radius if not provided.
// An empty object {} is passed to ensure params is defined in the Joystick constructor.
joystick = new Joystick({});
game.addChild(joystick);
// Position the joystick at the bottom-center of the screen
// joystick.base.width will be available after attachAsset in Joystick constructor
// Assuming joystick container's (x,y) is its center due to how assets are centered within it.
// To make joystick.x, joystick.y refer to its center:
joystick.x = GAME_WIDTH / 2;
// Position its center a bit up from the bottom edge
joystick.y = GAME_HEIGHT - joystick.base.height / 2 - 80; // 80px padding from bottom
// Event handler for touch/mouse down
game.down = function (x, y, obj) {
// Joystick always activates and moves its center to the touch position.
joystick.onDown(x, y); // Pass global coordinates. The 'obj' (event object) is not used by the new Joystick.onDown.
dragNode = joystick; // Joystick is the active drag target.
};
// Event handler for touch/mouse up
game.up = function (x, y, obj) {
if (dragNode === joystick) {
joystick.onUp(); // Deactivate the joystick
}
dragNode = null; // Clear the active drag target
};
// The old handleMove function is no longer needed as joystick handles movement logic.
// The assignment game.move = handleMove; is also removed.
// A new game.move will be defined next.
// Event handler for touch/mouse move
game.move = function (x, y, obj) {
if (dragNode === joystick) {
joystick.onMove(x, y, obj); // Pass move event to the joystick
}
};
// Main game update loop, called every frame by the LK engine.
game.update = function () {
// Player Movement Logic (based on joystick)
if (player && joystick) {
// Ensure player and joystick exist
var displacement = joystick.getDisplacement(); // Get normalized joystick output
if (displacement.dx !== 0 || displacement.dy !== 0) {
var newPlayerX = player.x + displacement.dx * PLAYER_MOVE_SPEED;
var newPlayerY = player.y + displacement.dy * PLAYER_MOVE_SPEED;
// Constrain player ship within screen boundaries.
// Player's x, y is its top-left corner.
player.x = Math.max(0, Math.min(GAME_WIDTH - player.width, newPlayerX));
player.y = Math.max(100, Math.min(GAME_HEIGHT - player.height, newPlayerY));
// --- Rotate player ship to face movement direction ---
if (typeof player.lastMoveAngle === "undefined") player.lastMoveAngle = 0;
var angle = Math.atan2(displacement.dy, displacement.dx);
// Only update rotation if there is movement (avoid NaN when joystick is idle)
if (displacement.dx !== 0 || displacement.dy !== 0) {
// The ship's default sprite faces up, so rotate by (angle - Math.PI/2)
player.rotation = angle - Math.PI / 2;
player.lastMoveAngle = player.rotation;
} else {
// If not moving, keep last rotation
player.rotation = player.lastMoveAngle;
}
}
}
// Player Shooting Logic
if (LK.ticks % PLAYER_SHOOT_INTERVAL_TICKS === 0 && player) {
// Added null check for player
// Calculate the direction the ship is facing (unit vector)
var shipAngle = typeof player.rotation === "number" ? player.rotation : 0;
var dirX = Math.cos(shipAngle + Math.PI / 2); // +PI/2 because sprite faces up
var dirY = Math.sin(shipAngle + Math.PI / 2);
// Calculate spawn position at the tip of the ship
var playerCenterX = player.x + player.width / 2;
var playerCenterY = player.y + player.height / 2;
// Distance from center to tip of ship (roughly half the height)
var tipDistance = player.height / 2;
// Offset for left/right cannons (perpendicular to direction)
// Move even further left: increase cannonOffset and invert sign for more leftward placement
var cannonOffset = 80; // increase for further left
var perpAngle = shipAngle + Math.PI; // perpendicular to ship's facing
var offsetX = Math.cos(shipAngle) * cannonOffset;
var offsetY = Math.sin(shipAngle) * cannonOffset;
// Calculate base spawn point at the tip of the ship
var baseX = playerCenterX + dirX * tipDistance;
var baseY = playerCenterY + dirY * tipDistance;
// Move the bullet spawn point slightly to the right (from previous much further left position)
var furtherLeftCannonX = baseX - Math.sin(shipAngle) * cannonOffset - 185; // moved 5px further to the right
var furtherLeftCannonY = baseY + Math.cos(shipAngle) * cannonOffset;
var bulletLeft = new PlayerBullet();
bulletLeft.x = furtherLeftCannonX - bulletLeft.width / 2;
bulletLeft.y = furtherLeftCannonY - bulletLeft.height / 2;
bulletLeft.direction = {
dx: dirX,
dy: dirY
};
bulletLeft.rotation = shipAngle;
bulletLeft.lastY = bulletLeft.y;
playerBullets.push(bulletLeft);
game.addChild(bulletLeft);
// Add a second bullet spawn point almost flush to the left side of the ship
// We'll place it just at the left edge of the ship's sprite, at the same Y as the tip
var leftEdgeOffset = -player.width / 2 + bulletLeft.width / 2 + 2; // 2px from the very left edge
var flushLeftCannonX = playerCenterX + leftEdgeOffset * Math.cos(shipAngle + Math.PI / 2);
var flushLeftCannonY = playerCenterY + leftEdgeOffset * Math.sin(shipAngle + Math.PI / 2);
// Place at the tip Y, but at the left edge X
var bulletFlushLeft = new PlayerBullet();
bulletFlushLeft.x = flushLeftCannonX - bulletFlushLeft.width / 2;
bulletFlushLeft.y = baseY - bulletFlushLeft.height / 2;
bulletFlushLeft.direction = {
dx: dirX,
dy: dirY
};
bulletFlushLeft.rotation = shipAngle;
bulletFlushLeft.lastY = bulletFlushLeft.y;
playerBullets.push(bulletFlushLeft);
game.addChild(bulletFlushLeft);
LK.getSound('playerShootSound').play();
}
// Enemy Spawning Logic
if (LK.ticks % ENEMY_SPAWN_INTERVAL_TICKS === 0) {
var newEnemy = new EnemyShip();
// Spawn enemy at a random X position, just off-screen at the top.
newEnemy.x = Math.random() * (GAME_WIDTH - newEnemy.width);
newEnemy.y = -newEnemy.height; // Starts just above the visible screen
newEnemy.lastY = newEnemy.y; // Initialize for off-screen transition
newEnemy.lastPlayerIntersecting = false; // Initialize for player collision transition
enemies.push(newEnemy);
game.addChild(newEnemy);
}
// Update Player Bullets (movement, off-screen removal, collision with enemies)
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
// bullet.update() is automatically called by LK engine for movement.
// Off-screen check (bullet moving upwards)
// Check if bullet's bottom edge (bullet.y + bullet.height) has crossed screen top (y=0)
if (bullet.y + bullet.height < 0 && bullet.lastY + bullet.height >= 0) {
bullet.destroy();
playerBullets.splice(i, 1);
continue; // Skip to next bullet
}
bullet.lastY = bullet.y; // Update lastY for next frame's transition check
// Collision with Enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
LK.setScore(LK.getScore() + 10); // Increment score
scoreTxt.setText('Score: ' + LK.getScore()); // Update score display
LK.getSound('enemyExplosionSound').play();
bullet.destroy(); // Destroy the bullet
playerBullets.splice(i, 1);
enemy.destroy(); // Destroy the enemy
enemies.splice(j, 1);
break; // Bullet hit one enemy, so it's gone.
}
}
}
// Update Enemies (movement, off-screen removal, collision with player)
for (var k = enemies.length - 1; k >= 0; k--) {
var enemy = enemies[k];
// enemy.update() is automatically called by LK engine.
// Off-screen check (enemy moving downwards)
// Check if enemy's top edge (enemy.y) has crossed screen bottom (y=GAME_HEIGHT)
if (enemy.y > GAME_HEIGHT && enemy.lastY <= GAME_HEIGHT) {
enemy.destroy();
enemies.splice(k, 1);
continue; // Skip to next enemy
}
enemy.lastY = enemy.y; // Update lastY for next frame
// Collision with Player
var currentPlayerIntersecting = player.intersects(enemy);
// Trigger game over only on the frame the intersection starts.
if (!enemy.lastPlayerIntersecting && currentPlayerIntersecting) {
LK.getSound('playerExplosionSound').play();
// LK.effects.flashScreen(0xFF0000, 300); // Optional screen flash
LK.showGameOver(); // End the game
return; // Exit update loop as game is over.
}
enemy.lastPlayerIntersecting = currentPlayerIntersecting; // Update intersection state
}
}; ===================================================================
--- original.js
+++ change.js
@@ -286,9 +286,9 @@
// Calculate base spawn point at the tip of the ship
var baseX = playerCenterX + dirX * tipDistance;
var baseY = playerCenterY + dirY * tipDistance;
// Move the bullet spawn point slightly to the right (from previous much further left position)
- var furtherLeftCannonX = baseX - Math.sin(shipAngle) * cannonOffset - 190; // moved 10px to the right
+ var furtherLeftCannonX = baseX - Math.sin(shipAngle) * cannonOffset - 185; // moved 5px further to the right
var furtherLeftCannonY = baseY + Math.cos(shipAngle) * cannonOffset;
var bulletLeft = new PlayerBullet();
bulletLeft.x = furtherLeftCannonX - bulletLeft.width / 2;
bulletLeft.y = furtherLeftCannonY - bulletLeft.height / 2;
Звездолет вид сверху два д для 2d игры пиксельный. In-Game asset
Красный лазерный луч пиксельный вид сверху. In-Game asset. 2d. High contrast. No shadows
Пиксельная шестерёнка с гаечным ключом. In-Game asset. 2d. High contrast. No shadows
Карточка с изоброжение скорости атака пиксельная карточка улучшения пиксельная космическая. In-Game asset. 2d. High contrast. No shadows
Карта усиления пиксельная усиливает скорость игрока космическая 2д пиксели. In-Game asset. 2d. High contrast. No shadows
Бронированный летающий корабль звездолет пиксельный вид сверху 2д. In-Game asset. 2d. High contrast. No shadows
Start в космической пмксельном стиле. In-Game asset. 2d. High contrast. No shadows
pixel inscription battle of starships in the style of space pixel art. In-Game asset. 2d. High contrast. No shadows
Карта усиления дающие + хп пиксельная космическая. In-Game asset. 2d. High contrast. No shadows
Пиксельная карта усиления атаки космос битва. In-Game asset. 2d. High contrast. No shadows
Карточка улучшения раздватвает атаку пиксельная в стиле космоса. In-Game asset. 2d. High contrast. No shadows
Пиксельная круглая кнопка атаки. In-Game asset. 2d. High contrast. No shadows
Пиксельный корабль сверху с нарисованным огнем спереди вид сверху. In-Game asset. 2d. High contrast. No shadows
Звездолет оформление в стиле призрака пиксельный вид сверху. In-Game asset. 2d. High contrast. No shadows
Пиксельная черная дыра желто черного цвета. In-Game asset. 2d. High contrast. No shadows