User prompt
For some reason, Heat-tipped arrows doesn't appear when choosing upgrades, fix that
User prompt
Archer ally uses "Archer" asset
User prompt
Archer ally shoots at enemies every 4 seconds; add an asset for him!
User prompt
Now, every 10 score, you can unlock one of these 3 of these 7 upgrades: Faster reaload (decreases the time to reaload), Piercing shots (Increases how many enemies an arrow can pierce through), Quiver (Increases how many arrows you can shoot before realoading), Heat-tipped arrows (Increases damage), Archer ally (You gain an archer ally that shoots arrows at enemies independently; his arrows don't affect the reload counter), Sabotage (enemies are slower), Swordsman (you gain a swordsman that attacks enemies on melee) ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Archer ally doesn't really do anything, Fix that by making him shoot every 3 seconds and by adding an asset for him ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Archer ally shoots at enemies every 4 seconds; add an asset for him!
User prompt
Now, every 10 score, you can unlock one upgrade of your choice of these 3 of these 7 upgrades: Faster reaload (decreases the time to reaload), Piercing shots (Increases how many enemies an arrow can pierce through), Quiver (Increases how many arrows you can shoot before realoading), Heat-tipped arrows (Increases damage), Archer ally (You gain an archer ally that shoots arrows at enemies independently; his arrows don't affect the reload counter), Sabotage (enemies are slower), Swordsman (you gain a swordsman that attacks enemies on melee)
User prompt
Now, every 10 score, you can unlock one of these 3 of these 7 upgrades: Faster reaload (decreases the time to reaload), Piercing shots (Increases how many enemies an arrow can pierce through), Quiver (Increases how many arrows you can shoot before realoading), Heat-tipped arrows (Increases damage), Archer ally (You gain an archer ally that shoots arrows at enemies independently; his arrows don't affect the reload counter), Sabotage (enemies are slower), Swordsman (you gain a swordsman that attacks enemies on melee)
User prompt
Now, every 10 score, you can unlock one of these 3 of these 7 upgrades: Faster reaload (decreases the time to reaload), Piercing shots (Increases how many enemies an arrow can pierce through), Quiver (Increases how many arrows you can shoot before realoading), Heat-tipped arrows (Increases damage), Archer ally (You gain an archer ally that shoots arrows at enemies independently; his arrows don't affect the reload counter), Sabotage (enemies are slower), Swordsman (you gain a swordsman that attacks enemies on melee)
User prompt
When playing, the song that plays now is "Game music"
User prompt
Now, when realoading, we do the "Reload" sound effect
User prompt
Add a 6 second cooldown after firing 15 arrows
Code edit (1 edits merged)
Please save this source code
User prompt
Archery Bastions
Initial prompt
Archery bastions
/**** * Classes ****/ // Sound when an enemy reaches the bastion // No plugins needed for this version of the game. /** * Represents an Arrow fired by the player. * @param {number} angle - The angle in radians at which the arrow is fired. */ var Arrow = Container.expand(function (angle) { var self = Container.call(this); // Create and attach the arrow graphic asset var graphics = self.attachAsset('arrow', { anchorX: 0.5, anchorY: 0.5 }); graphics.rotation = angle + Math.PI / 2; // Align arrow graphic with direction self.speed = 30; // Speed of the arrow in pixels per tick self.vx = Math.sin(angle) * self.speed; // Horizontal velocity component self.vy = -Math.cos(angle) * self.speed; // Vertical velocity component (negative Y is up) /** * Update method called each game tick by the LK engine. * Moves the arrow based on its velocity. */ self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; // Return self for potential inheritance }); /** * Represents an Enemy attacker moving towards the bastion. * @param {number} speed - The vertical speed of the enemy in pixels per tick. */ var Enemy = Container.expand(function (speed) { var self = Container.call(this); // Create and attach the enemy graphic asset var graphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.speed = speed; // Vertical speed (pixels per tick) /** * Update method called each game tick by the LK engine. * Moves the enemy downwards. */ self.update = function () { self.y += self.speed; }; return self; // Return self for potential inheritance }); /**** * Initialize Game ****/ // Create the main game instance with a dark background color. var game = new LK.Game({ backgroundColor: 0x101030 // Dark blue/purple background }); /**** * Game Code ****/ // Sound for an arrow hitting an enemy // Sound for firing an arrow // Grey line representing the bastion defense line // Red enemy shape // Yellow arrow shape // LK engine will automatically initialize these based on usage. // Define shapes and sounds needed for the game. // Constants defining game dimensions and key vertical positions. var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var BASTION_Y = GAME_HEIGHT - 250; // Y-coordinate representing the defense line. Enemies crossing this trigger game over. var FIRING_POS_Y = GAME_HEIGHT - 150; // Y-coordinate from where arrows are fired. var FIRING_POS_X = GAME_WIDTH / 2; // X-coordinate from where arrows are fired (center). // Arrays to keep track of active arrows and enemies. var arrows = []; var enemies = []; // Variables for game state and difficulty scaling. var scoreTxt; // Text2 object for displaying the score. var dragStartX = null; // Starting X coordinate of a touch/mouse drag. var dragStartY = null; // Starting Y coordinate of a touch/mouse drag. var enemySpawnInterval = 120; // Initial ticks between enemy spawns (2 seconds at 60 FPS). var arrowsFired = 0; // Counter for arrows fired since the last cooldown. var cooldownTimer = 0; // Timer in ticks for the cooldown period. var cooldownDuration = 6 * 60; // Cooldown duration in ticks (6 seconds * 60 ticks/sec). var minEnemySpawnInterval = 30; // Minimum ticks between enemy spawns (0.5 seconds). var enemySpawnRateDecrease = 0.08; // Amount to decrease spawn interval each time an enemy spawns. var currentEnemySpeed = 3; // Initial speed of enemies. var maxEnemySpeed = 12; // Maximum speed enemies can reach. var enemySpeedIncrease = 0.015; // Amount to increase enemy speed each time an enemy spawns. var upgradeThresholds = [10, 20, 30, 40, 50, 60, 70]; // Scores at which upgrades are offered var availableUpgrades = []; // Array to hold available upgrades at current score threshold var selectedUpgrade = null; // Holds the upgrade chosen by the player // --- Visual Setup --- // Create a visual line representing the bastion defense zone. var bastionLine = game.addChild(LK.getAsset('bastionLine', { anchorX: 0.0, // Anchor at the left edge. anchorY: 0.5, // Anchor vertically centered. x: 0, // Position at the left edge of the screen. y: BASTION_Y // Position at the defined bastion Y-coordinate. })); // Create and configure the score display text. scoreTxt = new Text2('0', { size: 150, // Font size. fill: 0xFFFFFF // White color. }); scoreTxt.anchor.set(0.5, 0); // Anchor at the horizontal center, top edge. // Add score text to the GUI layer at the top-center position. LK.gui.top.addChild(scoreTxt); scoreTxt.y = 30; // Add padding below the top edge. Ensure it's clear of the top-left menu icon area. // --- Input Event Handlers --- // Handles touch/mouse press down event on the game area. game.down = function (x, y, obj) { // Record the starting position of the drag in game coordinates. var gamePos = game.toLocal({ x: x, y: y }); dragStartX = gamePos.x; dragStartY = gamePos.y; // Potential enhancement: Show an aiming indicator originating from FIRING_POS_X, FIRING_POS_Y towards the drag point. }; // Handles touch/mouse move event while dragging on the game area. game.move = function (x, y, obj) { // Only process if a drag is currently active. if (dragStartX !== null) { var gamePos = game.toLocal({ x: x, y: y }); // Potential enhancement: Update the aiming indicator based on the current drag position (gamePos). } }; // Handles touch/mouse release event on the game area. game.up = function (x, y, obj) { // Only process if a drag was active. if (dragStartX !== null && cooldownTimer <= 0) { // Only allow firing if not on cooldown. var gamePos = game.toLocal({ x: x, y: y }); var dragEndX = gamePos.x; var dragEndY = gamePos.y; // Calculate the difference between the firing position and the release point to determine direction. // A longer drag could potentially mean more power, but we'll keep it simple: direction only. var dx = dragEndX - FIRING_POS_X; var dy = dragEndY - FIRING_POS_Y; // Avoid division by zero or zero vector if start and end points are the same. if (dx === 0 && dy === 0) { // Optionally handle this case, e.g., fire straight up or do nothing. // Let's fire straight up if drag distance is negligible. dy = -1; } // Calculate the angle using atan2. Note the order (dx, dy) and the negation of dy // because the Y-axis is inverted in screen coordinates (positive Y is down). var angle = Math.atan2(dx, -dy); // Create a new arrow instance with the calculated angle. var newArrow = new Arrow(angle); newArrow.x = FIRING_POS_X; newArrow.y = FIRING_POS_Y; // Initialize last position for state tracking (e.g., off-screen detection) newArrow.lastY = newArrow.y; newArrow.lastX = newArrow.x; // Add the arrow to the game scene and the tracking array. game.addChild(newArrow); arrows.push(newArrow); LK.getSound('shoot').play(); // Play shooting sound. arrowsFired++; // Increment arrow count. if (arrowsFired >= 15) { cooldownTimer = cooldownDuration; // Start cooldown. arrowsFired = 0; // Reset arrow count. LK.getSound('Reload').play(); // Play reload sound. } // Reset drag state. dragStartX = null; dragStartY = null; // Potential enhancement: Hide the aiming indicator. } }; // --- Main Game Update Loop --- // This function is called automatically by the LK engine on every frame (tick). game.update = function () { // Decrease cooldown timer if active. if (cooldownTimer > 0) { cooldownTimer--; } // 1. Update and check Arrows for (var i = arrows.length - 1; i >= 0; i--) { var arrow = arrows[i]; // Note: LK engine calls arrow.update() automatically as it's added to the game stage. // Initialize last position if it hasn't been set yet (first frame). if (arrow.lastY === undefined) { arrow.lastY = arrow.y; } if (arrow.lastX === undefined) { arrow.lastX = arrow.x; } // Check for collisions between the current arrow and all enemies. var hitEnemy = false; for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; // Use the intersects method for collision detection. if (arrow.intersects(enemy)) { // Collision detected! LK.setScore(LK.getScore() + 1); // Increment score. scoreTxt.setText(LK.getScore()); // Update score display. LK.getSound('hit').play(); // Play hit sound. // Destroy the enemy and the arrow involved in the collision. enemy.destroy(); enemies.splice(j, 1); // Remove enemy from array. arrow.destroy(); arrows.splice(i, 1); // Remove arrow from array. hitEnemy = true; // Mark that a hit occurred. break; // An arrow can only hit one enemy per frame; stop checking this arrow. } } // If the arrow hit an enemy, it was destroyed, so skip to the next arrow. if (hitEnemy) { continue; } // Check if the arrow has gone off-screen (top, left, or right). // Use transition detection: check if it was on screen last frame and is off screen now. var wasOnScreen = arrow.lastY > -arrow.height / 2 && arrow.lastX > -arrow.width / 2 && arrow.lastX < GAME_WIDTH + arrow.width / 2; var isOffScreen = arrow.y < -arrow.height / 2 || // Off top edge arrow.x < -arrow.width / 2 || // Off left edge arrow.x > GAME_WIDTH + arrow.width / 2; // Off right edge if (wasOnScreen && isOffScreen) { // Arrow is off-screen, destroy it and remove from the array. arrow.destroy(); arrows.splice(i, 1); } else if (!isOffScreen) { // Update last known position only if the arrow is still potentially on screen arrow.lastY = arrow.y; arrow.lastX = arrow.x; } } // 2. Update and check Enemies for (var k = enemies.length - 1; k >= 0; k--) { var enemy = enemies[k]; // Note: LK engine calls enemy.update() automatically. // Initialize last position if not set. if (enemy.lastY === undefined) { enemy.lastY = enemy.y; } // Check if the enemy has reached or passed the bastion line. // Use transition detection: was the enemy's bottom edge above the line last frame, // and is it on or below the line now? var enemyBottomY = enemy.y + enemy.height / 2; var enemyLastBottomY = enemy.lastY + enemy.height / 2; var wasAboveBastion = enemyLastBottomY < BASTION_Y; var isAtOrBelowBastion = enemyBottomY >= BASTION_Y; if (wasAboveBastion && isAtOrBelowBastion) { // Enemy reached the bastion! Game Over. LK.getSound('gameOverSfx').play(); // Play game over sound effect. LK.showGameOver(); // Trigger the engine's game over sequence. // LK.showGameOver handles game state reset, no need to manually clear arrays here. return; // Exit the update loop immediately as the game is over. } else { // Update last known position if game is not over for this enemy. enemy.lastY = enemy.y; } } // Check if an upgrade is available at the current score if (upgradeThresholds.includes(LK.getScore())) { // Prevent multiple upgrade triggers at the same score var thresholdIndex = upgradeThresholds.indexOf(LK.getScore()); if (!game.upgradeOffered || game.upgradeThresholdReached < thresholdIndex) { game.upgradeOffered = true; game.upgradeThresholdReached = thresholdIndex; offerUpgrade(); // Function to present upgrade options to the player } } // 3. Spawn new Enemies periodically // Use LK.ticks and the spawn interval. Ensure interval doesn't go below minimum. if (LK.ticks % Math.max(minEnemySpawnInterval, Math.floor(enemySpawnInterval)) === 0) { // Determine the speed for the new enemy, capping at max speed. var newEnemySpeed = Math.min(maxEnemySpeed, currentEnemySpeed); var newEnemy = new Enemy(newEnemySpeed); // Position the new enemy at the top of the screen at a random horizontal position. // Add padding to avoid spawning exactly at the screen edges. var spawnPadding = newEnemy.width / 2 + 20; // Add a little extra padding newEnemy.x = spawnPadding + Math.random() * (GAME_WIDTH - 2 * spawnPadding); newEnemy.y = -newEnemy.height / 2; // Start just above the top edge. // Initialize last position for state tracking. newEnemy.lastY = newEnemy.y; // Add the new enemy to the game scene and the tracking array. game.addChild(newEnemy); enemies.push(newEnemy); // Increase difficulty for the next spawn: decrease spawn interval and increase speed. enemySpawnInterval -= enemySpawnRateDecrease; currentEnemySpeed += enemySpeedIncrease; } }; // --- Initial Game Setup --- // Set the initial score text based on the starting score (which is 0). scoreTxt.setText(LK.getScore()); ; // Play the background music. LK.playMusic('Gamemusic'); ; function offerUpgrade() { // Define all possible upgrades var allUpgrades = [{ name: "Faster Reload", description: "Decreases reload time.", effect: "decreaseCooldown", value: 60 }, // Decrease by 1 second (60 ticks) { name: "Piercing Shots", description: "Arrows pierce more enemies.", effect: "increasePierce", value: 1 }, // Increase pierce count by 1 { name: "Quiver", description: "Shoot more arrows before reloading.", effect: "increaseQuiver", value: 5 }, // Increase arrow limit by 5 { name: "Heat-tipped Arrows", description: "Increases arrow damage.", effect: "increaseDamage", value: 1 }, // Placeholder for damage (not implemented yet) { name: "Archer Ally", description: "Gain an archer ally.", effect: "addArcherAlly" }, // Add an archer ally { name: "Sabotage", description: "Enemies are slower.", effect: "slowEnemies", value: 0.5 }, // Decrease enemy speed multiplier { name: "Swordsman", description: "Gain a swordsman ally.", effect: "addSwordsmanAlly" } // Add a swordsman ally ]; // Select 3 random, unique upgrades availableUpgrades = []; while (availableUpgrades.length < 3 && allUpgrades.length > 0) { var randomIndex = Math.floor(Math.random() * allUpgrades.length); availableUpgrades.push(allUpgrades.splice(randomIndex, 1)[0]); } // Pause the game and display upgrade options (Placeholder - requires UI implementation) console.log("UPGRADE TIME! Choose one:"); availableUpgrades.forEach(function (upgrade, index) { console.log(index + 1 + ". " + upgrade.name + ": " + upgrade.description); }); // In a real game, you would create UI elements for these choices and handle player selection. // For now, we'll simulate a selection or wait for further instructions on UI. // For testing, let's automatically pick the first upgrade available. // selectedUpgrade = availableUpgrades[0]; // applyUpgrade(selectedUpgrade); // game.upgradeOffered = false; // Reset flag // LK.unpauseGame(); // Unpause the game after selection (Placeholder) } function applyUpgrade(upgrade) { console.log("Applying upgrade: " + upgrade.name); switch (upgrade.effect) { case "decreaseCooldown": cooldownDuration = Math.max(60, cooldownDuration - upgrade.value); // Ensure minimum cooldown of 1 second break; case "increasePierce": // Placeholder: Implement logic to track and apply piercing shots break; case "increaseQuiver": // Placeholder: Implement logic to increase the arrow limit before reload break; case "increaseDamage": // Placeholder: Implement logic to increase arrow damage break; case "addArcherAlly": // Placeholder: Implement logic to create and manage an Archer Ally break; case "slowEnemies": // Placeholder: Implement logic to apply a speed multiplier to enemies break; case "addSwordsmanAlly": // Placeholder: Implement logic to create and manage a Swordsman Ally break; } }
===================================================================
--- original.js
+++ change.js
@@ -60,16 +60,16 @@
/****
* Game Code
****/
-// Constants defining game dimensions and key vertical positions.
-// Define shapes and sounds needed for the game.
-// LK engine will automatically initialize these based on usage.
-// Yellow arrow shape
-// Red enemy shape
-// Grey line representing the bastion defense line
-// Sound for firing an arrow
// Sound for an arrow hitting an enemy
+// Sound for firing an arrow
+// Grey line representing the bastion defense line
+// Red enemy shape
+// Yellow arrow shape
+// LK engine will automatically initialize these based on usage.
+// Define shapes and sounds needed for the game.
+// Constants defining game dimensions and key vertical positions.
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var BASTION_Y = GAME_HEIGHT - 250; // Y-coordinate representing the defense line. Enemies crossing this trigger game over.
var FIRING_POS_Y = GAME_HEIGHT - 150; // Y-coordinate from where arrows are fired.
@@ -89,8 +89,11 @@
var enemySpawnRateDecrease = 0.08; // Amount to decrease spawn interval each time an enemy spawns.
var currentEnemySpeed = 3; // Initial speed of enemies.
var maxEnemySpeed = 12; // Maximum speed enemies can reach.
var enemySpeedIncrease = 0.015; // Amount to increase enemy speed each time an enemy spawns.
+var upgradeThresholds = [10, 20, 30, 40, 50, 60, 70]; // Scores at which upgrades are offered
+var availableUpgrades = []; // Array to hold available upgrades at current score threshold
+var selectedUpgrade = null; // Holds the upgrade chosen by the player
// --- Visual Setup ---
// Create a visual line representing the bastion defense zone.
var bastionLine = game.addChild(LK.getAsset('bastionLine', {
anchorX: 0.0,
@@ -265,8 +268,18 @@
// Update last known position if game is not over for this enemy.
enemy.lastY = enemy.y;
}
}
+ // Check if an upgrade is available at the current score
+ if (upgradeThresholds.includes(LK.getScore())) {
+ // Prevent multiple upgrade triggers at the same score
+ var thresholdIndex = upgradeThresholds.indexOf(LK.getScore());
+ if (!game.upgradeOffered || game.upgradeThresholdReached < thresholdIndex) {
+ game.upgradeOffered = true;
+ game.upgradeThresholdReached = thresholdIndex;
+ offerUpgrade(); // Function to present upgrade options to the player
+ }
+ }
// 3. Spawn new Enemies periodically
// Use LK.ticks and the spawn interval. Ensure interval doesn't go below minimum.
if (LK.ticks % Math.max(minEnemySpawnInterval, Math.floor(enemySpawnInterval)) === 0) {
// Determine the speed for the new enemy, capping at max speed.
@@ -291,5 +304,100 @@
// Set the initial score text based on the starting score (which is 0).
scoreTxt.setText(LK.getScore());
;
// Play the background music.
-LK.playMusic('Gamemusic');
\ No newline at end of file
+LK.playMusic('Gamemusic');
+;
+function offerUpgrade() {
+ // Define all possible upgrades
+ var allUpgrades = [{
+ name: "Faster Reload",
+ description: "Decreases reload time.",
+ effect: "decreaseCooldown",
+ value: 60
+ },
+ // Decrease by 1 second (60 ticks)
+ {
+ name: "Piercing Shots",
+ description: "Arrows pierce more enemies.",
+ effect: "increasePierce",
+ value: 1
+ },
+ // Increase pierce count by 1
+ {
+ name: "Quiver",
+ description: "Shoot more arrows before reloading.",
+ effect: "increaseQuiver",
+ value: 5
+ },
+ // Increase arrow limit by 5
+ {
+ name: "Heat-tipped Arrows",
+ description: "Increases arrow damage.",
+ effect: "increaseDamage",
+ value: 1
+ },
+ // Placeholder for damage (not implemented yet)
+ {
+ name: "Archer Ally",
+ description: "Gain an archer ally.",
+ effect: "addArcherAlly"
+ },
+ // Add an archer ally
+ {
+ name: "Sabotage",
+ description: "Enemies are slower.",
+ effect: "slowEnemies",
+ value: 0.5
+ },
+ // Decrease enemy speed multiplier
+ {
+ name: "Swordsman",
+ description: "Gain a swordsman ally.",
+ effect: "addSwordsmanAlly"
+ } // Add a swordsman ally
+ ];
+ // Select 3 random, unique upgrades
+ availableUpgrades = [];
+ while (availableUpgrades.length < 3 && allUpgrades.length > 0) {
+ var randomIndex = Math.floor(Math.random() * allUpgrades.length);
+ availableUpgrades.push(allUpgrades.splice(randomIndex, 1)[0]);
+ }
+ // Pause the game and display upgrade options (Placeholder - requires UI implementation)
+ console.log("UPGRADE TIME! Choose one:");
+ availableUpgrades.forEach(function (upgrade, index) {
+ console.log(index + 1 + ". " + upgrade.name + ": " + upgrade.description);
+ });
+ // In a real game, you would create UI elements for these choices and handle player selection.
+ // For now, we'll simulate a selection or wait for further instructions on UI.
+ // For testing, let's automatically pick the first upgrade available.
+ // selectedUpgrade = availableUpgrades[0];
+ // applyUpgrade(selectedUpgrade);
+ // game.upgradeOffered = false; // Reset flag
+ // LK.unpauseGame(); // Unpause the game after selection (Placeholder)
+}
+function applyUpgrade(upgrade) {
+ console.log("Applying upgrade: " + upgrade.name);
+ switch (upgrade.effect) {
+ case "decreaseCooldown":
+ cooldownDuration = Math.max(60, cooldownDuration - upgrade.value); // Ensure minimum cooldown of 1 second
+ break;
+ case "increasePierce":
+ // Placeholder: Implement logic to track and apply piercing shots
+ break;
+ case "increaseQuiver":
+ // Placeholder: Implement logic to increase the arrow limit before reload
+ break;
+ case "increaseDamage":
+ // Placeholder: Implement logic to increase arrow damage
+ break;
+ case "addArcherAlly":
+ // Placeholder: Implement logic to create and manage an Archer Ally
+ break;
+ case "slowEnemies":
+ // Placeholder: Implement logic to apply a speed multiplier to enemies
+ break;
+ case "addSwordsmanAlly":
+ // Placeholder: Implement logic to create and manage a Swordsman Ally
+ break;
+ }
+}
\ No newline at end of file
Arrow. In-Game asset. 2d. High contrast. No shadows. Topdown
Red stickman with a sword. In-Game asset. 2d. High contrast. No shadows. Topdown
Blue stickman with a bow. In-Game asset. 2d. High contrast. No shadows
Red stickman with an iron helmet, iron sword and iron shield. In-Game asset. 2d. High contrast. No shadows. No eyes
Red stickman with a knife and a thief's bandana. In-Game asset. 2d. High contrast. No shadows. No eyes
Purple stickman with a crown. In-Game asset. 2d. High contrast. No shadows
Blue stickman with a sword. In-Game asset. 2d. High contrast. No shadows
Tower. In-Game asset. 2d. High contrast. No shadows
Red stickman with a big wooden shield full of spikes. In-Game asset. 2d. High contrast. No shadows
Green stickman with a blue wizard hat and a staff; no eyes. In-Game asset. 2d. High contrast. No shadows
Red stickman with a golden knight helmet, gold sword and gold shield and gold boots. In-Game asset. 2d. High contrast. No shadows
Cannon. In-Game asset. 2d. High contrast. No shadows
Cannonball. In-Game asset. 2d. High contrast. No shadows
Yellow stickman with an azur wizard hat and staff on a tower. In-Game asset. 2d. High contrast. No shadows
Magic ice ball. In-Game asset. 2d. High contrast. No shadows
Green stickman with a Spartan helmet, Spartan shield and Spartan spear. In-Game asset. 2d. High contrast. No shadows
Green war elephant. In-Game asset. 2d. High contrast. No shadows
Yellow viking stickman holding an axe and is about to throw it. In-Game asset. 2d. High contrast. No shadows
Hatchet. In-Game asset. 2d. High contrast. No shadows