Code edit (3 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'player._speedBoostTimeout = setTimeout(function () {' Line Number: 1030
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 907
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 911
Code edit (3 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'player._speedBoostTimeout = setTimeout(function () {' Line Number: 967
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 922
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'wait')' in or related to this line: 'tween(shieldEffect).wait(4000).to({' Line Number: 779
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(scoreText).to({' Line Number: 855
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween({' Line Number: 718
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(player.children[0]).to({' Line Number: 717
User prompt
Please fix the bug: 'TypeError: Invalid value used as weak map key' in or related to this line: 'tween(player.children[0].style).to({' Line Number: 717
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(player.children[0]).to({' Line Number: 715
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(scoreText).to({' Line Number: 855
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(scoreText).to({' Line Number: 855
Code edit (3 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(scoreText).to({' Line Number: 898
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: tween.get is not a function' in or related to this line: 'tween.get(scoreText).to({' Line Number: 898
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
milestones: []
});
/****
* Classes
****/
// On-screen left/right controls for mobile
var AsciiButton = Container.expand(function () {
var self = Container.call(this);
self.txt = self.addChild(new Text2("", {
size: 120,
fill: 0xFFFFFF,
font: "monospace"
}));
self.txt.anchor.set(0.5, 0.5);
self.setLabel = function (label) {
self.txt.setText(label);
};
return self;
});
// ASCII Obstacle
var AsciiObstacle = Container.expand(function () {
var self = Container.call(this);
// Randomly choose an ASCII obstacle shape, now with more funny blocks!
var shapes = ["#####", "=====", "-----", "|||||", "oOoOo",
// funny bouncy
"UwU",
// cute face
"0v0v0",
// zigzag
"><(((º>",
// fish
"LOL",
// meme
":-)",
// smiley
"ZZZZZ",
// sleepy
"MOO",
// cow
"BEEP",
// robot
"!!!",
// exclamation
"T_T",
// sad face
"12345",
// numbers
"abcde" // letters
];
var ascii = shapes[Math.floor(Math.random() * shapes.length)];
var obsText = self.addChild(new Text2(ascii, {
size: 90,
fill: 0xFF5555,
font: "monospace"
}));
obsText.anchor.set(0.5, 0.5);
// For collision, define a bounding box
self.getBounds = function () {
return {
x: self.x - 225,
y: self.y - 45,
width: 450,
height: 90
};
};
// Move down at a variable speed (default 12, can be overridden)
self.speed = 12;
self.update = function () {
if (typeof self.lastY === "undefined") {
self.lastY = self.y;
}
self.y += self.speed;
self.lastY = self.y;
};
return self;
});
// ASCII Player Character
var AsciiPlayer = Container.expand(function () {
var self = Container.call(this);
// ASCII art for the player (simple stick figure)
var asciiArt = [" O ", " /|\\ ", " / \\ "].join("\n");
var playerText = self.addChild(new Text2(asciiArt, {
size: 90,
fill: 0xFFFFFF,
font: "monospace"
}));
playerText.anchor.set(0.5, 0.5);
// Cosmetic tag above head (for rewards)
self.tagText = self.addChild(new Text2("", {
size: 60,
fill: 0x00FF99,
font: "monospace"
}));
self.tagText.anchor.set(0.5, 1);
self.tagText.x = 0;
self.tagText.y = -140;
// Cosmetic border container
self.borderBox = new Container();
self.addChild(self.borderBox);
// Function to update border style
self.updateBorder = function (score) {
// Remove previous border
if (self.borderBox.children.length > 0) {
for (var i = 0; i < self.borderBox.children.length; i++) {
self.borderBox.children[i].destroy();
}
self.borderBox.removeChildren();
}
// Choose border style by score
var borderStyle = Math.floor(score / 100) % 6; // her 100 puanda değişir
var borderArt = "";
var borderColor = 0xFFFFFF;
if (score >= 100) {
borderColor = Math.random() * 0xFFFFFF; // Rastgele renk (istediğin gibi değiştir)
switch (borderStyle) {
case 0:
borderArt = "+-----+\n| |\n| |\n+-----+";
break;
case 1:
borderArt = "☆-----☆\n| |\n| |\n☆-----☆";
break;
case 2:
borderArt = "🔥-----🔥\n| |\n| |\n🔥-----🔥";
break;
case 3:
borderArt = "▓▓▓▓▓▓▓\n| |\n| |\n▓▓▓▓▓▓▓";
break;
case 4:
borderArt = "♡-----♡\n| |\n| |\n♡-----♡";
break;
case 5:
borderArt = "◆-----◆\n| |\n| |\n◆-----◆";
break;
}
} else {
switch (borderStyle) {
case 0:
borderArt = "+-----+\n| |\n| |\n+-----+";
borderColor = 0xAAAAAA;
break;
case 1:
borderArt = "☆-----☆\n| |\n| |\n☆-----☆";
borderColor = 0xFFD700;
break;
case 2:
borderArt = "🔥-----🔥\n| |\n| |\n🔥-----🔥";
borderColor = 0xFF5500;
break;
case 3:
borderArt = "▓▓▓▓▓▓▓\n| |\n| |\n▓▓▓▓▓▓▓";
borderColor = 0x00FFFF;
break;
case 4:
borderArt = "♡-----♡\n| |\n| |\n♡-----♡";
borderColor = 0xFF66CC;
break;
case 5:
borderArt = "◆-----◆\n| |\n| |\n◆-----◆";
borderColor = 0x66FF99;
break;
}
}
var borderTxt = new Text2(borderArt, {
size: 100,
fill: borderColor,
font: "monospace"
});
borderTxt.anchor.set(0.5, 0.5);
borderTxt.x = 0;
borderTxt.y = 0;
self.borderBox.addChild(borderTxt);
};
self._walkFrame = 0;
self._walkFrames = [[" O ", " /|\\ ", " / \\ "].join("\n"),
// Normal duruş
[" O ", " /|\\ ", " / "].join("\n"),
// Tek bacak yukarı
[" O ", " /|\\ ", " \\ "].join("\n") // Diğer bacak yukarı
];
self.update = function () {
// Basit yürüme animasyonu (her 10 tick'te bir kare değiştir)
if (LK.ticks % 10 === 0) {
playerText.setText(self._walkFrames[self._walkFrame]); // playerText'e erişim
self._walkFrame = (self._walkFrame + 1) % self._walkFrames.length;
}
};
// For collision, define a bounding box
self.getBounds = function () {
return {
x: self.x - 90,
y: self.y - 135,
width: 180,
height: 270
};
};
return self;
});
// Power-up: Point Magnet
var PointMagnetPowerup = Container.expand(function () {
var self = Container.call(this);
var magnetText = self.addChild(new Text2("[MAGNET]", {
size: 80,
fill: 0xFF00FF,
// Mor renk
font: "monospace"
}));
magnetText.anchor.set(0.5, 0.5);
self.speed = 10;
self.duration = 6000; // 6 saniye süre
self.attractionRange = 500; // Mıknatıs çekim mesafesi
self.getBounds = function () {
return {
x: self.x - 120,
y: self.y - 40,
width: 240,
height: 80
};
};
self.update = function () {
if (typeof self.lastY === "undefined") {
self.lastY = self.y;
}
self.y += self.speed;
self.lastY = self.y;
};
return self;
});
// Power-up: Score Multiplier
var ScoreMultiplierPowerup = Container.expand(function () {
var self = Container.call(this);
var multiplierText = self.addChild(new Text2("[2x SCORE]", {
size: 80,
fill: 0x99FF00,
// Yeşil renk
font: "monospace"
}));
multiplierText.anchor.set(0.5, 0.5);
self.speed = 10;
self.duration = 7000; // 7 saniye süre
self.multiplier = 2; // Çarpan değeri
self.getBounds = function () {
return {
x: self.x - 180,
y: self.y - 40,
width: 360,
height: 80
};
};
self.update = function () {
if (typeof self.lastY === "undefined") {
self.lastY = self.y;
}
self.y += self.speed;
self.lastY = self.y;
};
return self;
});
// Power-up: Shield
var ShieldPowerup = Container.expand(function () {
var self = Container.call(this);
var shieldText = self.addChild(new Text2("[SHIELD]", {
size: 80,
fill: 0x00FFFF,
font: "monospace"
}));
shieldText.anchor.set(0.5, 0.5);
self.speed = 10;
self.getBounds = function () {
return {
x: self.x - 120,
y: self.y - 40,
width: 240,
height: 80
};
};
self.update = function () {
if (typeof self.lastY === "undefined") {
self.lastY = self.y;
}
self.y += self.speed;
self.lastY = self.y;
};
return self;
});
// Power-up: Speed Boost
var SpeedBoostPowerup = Container.expand(function () {
var self = Container.call(this);
var speedText = self.addChild(new Text2("[SPEED]", {
size: 80,
fill: 0xFFD700,
// Altın rengi
font: "monospace"
}));
speedText.anchor.set(0.5, 0.5);
self.speed = 10; // Power-up düşme hızı
self.duration = 5000; // 5 saniye hız artışı süresi
self.getBounds = function () {
return {
x: self.x - 120,
y: self.y - 40,
width: 240,
height: 80
};
};
self.update = function () {
if (typeof self.lastY === "undefined") {
self.lastY = self.y;
}
self.y += self.speed;
self.lastY = self.y;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Storage for persistent profile/milestones
function _typeof2(o) {
"@babel/helpers - typeof";
return _typeof2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof2(o);
}
function _classCallCheck2(a, n) {
if (!(a instanceof n)) {
throw new TypeError("Cannot call a class as a function");
}
}
function __defineProperties(e, r) {
for (var t = 0; t < r.length; t++) {
var o = r[t];
o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey2(o.key), o);
}
}
function _createClass2(e, r, t) {
return r && __defineProperties(e.prototype, r), t && __defineProperties(e, t), Object.defineProperty(e, "prototype", {
writable: !1
}), e;
}
function _toPropertyKey2(t) {
var i = _toPrimitive2(t, "string");
return "symbol" == _typeof2(i) ? i : i + "";
}
function _toPrimitive2(t, r) {
if ("object" != _typeof2(t) || !t) {
return t;
}
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != _typeof2(i)) {
return i;
}
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
function _classCallCheck(a, n) {
if (!(a instanceof n)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(e, r) {
for (var t = 0; t < r.length; t++) {
var o = r[t];
o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
}
}
function _createClass(e, r, t) {
return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
writable: !1
}), e;
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == _typeof(i) ? i : i + "";
}
function _toPrimitive(t, r) {
if ("object" != _typeof(t) || !t) {
return t;
}
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != _typeof(i)) {
return i;
}
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
var STATE_MENU = 0;
var STATE_PLAY = 1;
var STATE_PROFILE = 2;
var gameState = STATE_MENU;
// Main elements
var player;
var obstacles = [];
var powerups = []; // Make powerups globally defined so it is accessible everywhere
var score = 0;
var bestScore = storage.bestScore || 0;
var milestones = storage.milestones || [];
var milestoneThresholds = [10, 25, 50, 100, 200, 500, 1000];
// New game state variables
var health = 3;
var maxHealth = 5;
var combo = 0;
var lastCosmetic = -1;
var cosmeticTags = ["", "ASCII MAN", "ASCII PRO", "RUNNER", "ELITE", "ASCII KING", "GODMODE", "AMAZİNG", "777", "SHİT", "ADMİN"];
// Power-up state trackers
game._lastShieldScore = -1; // Reset shield drop tracker
game._lastSpeedBoostScore = -1;
game._lastScoreMultiplierScore = -1;
game._lastPointMagnetScore = -1; // Yeni: Point Magnet drop takipçisi
game._currentScoreMultiplier = 1; // Başlangıçta çarpan 1
game._isMagnetActive = false; // Yeni: Mıknatıs durumu
game._lastBgColorScore = -1; // Arka plan rengi değişimi takipçisi
// GUI elements
var scoreText, bestText, menuTitle, startBtn, profileBtn, profilePanel, profileTitle, profileMilestones, backBtn;
var healthText; // Make healthText globally defined so it is accessible everywhere
var comboText; // New: Combo text
var leftBtn; // Make leftBtn globally defined so it is accessible everywhere
var rightBtn; // Make rightBtn globally defined so it is accessible everywhere
// Utility: collision detection (AABB)
function intersects(a, b) {
var ab = a.getBounds();
var bb = b.getBounds();
return ab.x < bb.x + bb.width && ab.x + ab.width > bb.x && ab.y < bb.y + bb.height && ab.y + ab.height > bb.y;
}
// Utility: get distance between two points
function getDistance(obj1, obj2) {
var dx = obj1.x - obj2.x;
var dy = obj1.y - obj2.y;
return Math.sqrt(dx * dx + dy * dy);
}
// --- MENU UI ---
function showMenu() {
gameState = STATE_MENU;
clearGame(); // Oyun içi öğeleri temizle
clearProfile(); // Profil ekranı öğelerini temizle
clearMenu(); // Menü öğelerini temizle (önceki menüden kalıntıları silmek için)
// Title
menuTitle = new Text2("ASCII RUNNER", {
size: 140,
fill: 0xFFFFFF,
font: "monospace"
});
menuTitle.anchor.set(0.5, 0);
menuTitle.x = 2048 / 2;
menuTitle.y = 300;
game.addChild(menuTitle);
// Start Button (always enabled, no username required)
startBtn = new Text2("[ START ]", {
size: 110,
fill: 0x00FF99,
font: "monospace"
});
startBtn.anchor.set(0.5, 0.5);
startBtn.x = 2048 / 2;
startBtn.y = 900;
startBtn.alpha = 1;
startBtn.down = function () {
clearMenu(); // Menü öğelerini kaldır
startGame();
};
game.addChild(startBtn);
// Profile Button
profileBtn = new Text2("[ PROFILE ]", {
size: 90,
fill: 0xCCCCCC,
font: "monospace"
});
profileBtn.anchor.set(0.5, 0.5);
profileBtn.x = 2048 / 2;
profileBtn.y = 1600;
game.addChild(profileBtn);
// Best Score - Scoreboard'u üst tarafa taşıyoruz.
bestText = new Text2("Best: " + bestScore, {
size: 80,
fill: 0xAAAAAA,
font: "monospace"
});
bestText.anchor.set(0.5, 0); // Üst merkeze hizala
bestText.x = 2048 / 2;
bestText.y = 20; // Ekranın en üstüne biraz boşluk bırakarak yerleştir
LK.gui.top.addChild(bestText); // LK.gui.top'a ekliyoruz ki her zaman görünür olsun
// Button handlers
profileBtn.down = function () {
showProfile();
};
}
// --- PROFILE UI ---
function showProfile() {
gameState = STATE_PROFILE;
clearMenu(); // Menü öğelerini temizle
clearGame(); // Oyun içi öğeleri temizle
profilePanel = new Container();
// Username at top
var uname = typeof username !== "undefined" && username ? username : storage.username || "";
var unameText = new Text2(uname, {
size: 90,
fill: 0x00FF99,
font: "monospace"
});
unameText.anchor.set(0.5, 0);
unameText.x = 2048 / 2;
unameText.y = 180;
profilePanel.addChild(unameText);
// Title
profileTitle = new Text2("PROFILE", {
size: 120,
fill: 0xFFFFFF,
font: "monospace"
});
profileTitle.anchor.set(0.5, 0);
profileTitle.x = 2048 / 2;
profileTitle.y = 300;
profilePanel.addChild(profileTitle);
// Milestones
var milestoneLines = [];
for (var i = 0; i < milestoneThresholds.length; i++) {
var th = milestoneThresholds[i];
var unlocked = milestones.indexOf(th) !== -1;
milestoneLines.push((unlocked ? "[✓] " : "[ ] ") + "Score " + th);
}
profileMilestones = new Text2(milestoneLines.join("\n"), {
size: 90,
fill: 0xFFFF99,
font: "monospace"
});
profileMilestones.anchor.set(0.5, 0);
profileMilestones.x = 2048 / 2;
profileMilestones.y = 500;
profilePanel.addChild(profileMilestones);
// Back Button
backBtn = new Text2("[ BACK ]", {
size: 90,
fill: 0x00FF99,
font: "monospace"
});
backBtn.anchor.set(0.5, 0.5);
backBtn.x = 2048 / 2;
backBtn.y = 1800;
profilePanel.addChild(backBtn);
backBtn.down = function () {
showMenu();
};
game.addChild(profilePanel);
}
// --- GAMEPLAY UI ---
function startGame() {
gameState = STATE_PLAY;
clearMenu(); // Menü öğelerini kaldır (bestText dahil)
clearProfile(); // Profil öğelerini kaldır
score = 0;
obstacles = [];
powerups = [];
health = 3;
maxHealth = 5;
combo = 0;
lastCosmetic = -1;
game._lastShieldScore = -1; // Reset shield drop tracker
game._lastSpeedBoostScore = -1; // Reset speed boost tracker
game._lastScoreMultiplierScore = -1; // Reset score multiplier tracker
game._lastPointMagnetScore = -1; // Yeni: Point Magnet drop takipçisi
game._currentScoreMultiplier = 1; // Reset score multiplier
game._isMagnetActive = false; // Yeni: Mıknatıs durumu
game._lastBgColorScore = -1; // Reset background color tracker
// Player
player = new AsciiPlayer();
player.x = 2048 / 2;
player.y = 2200;
game.addChild(player);
// İlk borderı göster
player.updateBorder(score);
// Score Text (oyun içi - LK.gui.top'a ekleniyor)
scoreText = new Text2("Score: 0", {
size: 100,
fill: 0xFFFFFF,
font: "monospace"
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 2048 / 2;
scoreText.y = 0; // Ekranın en üstünde
LK.gui.top.addChild(scoreText); // Bu satır skor metnini üst GUI katmanına ekler
// Combo Text (Yeni - LK.gui.top'a ekleniyor)
comboText = new Text2("Combo: 0", {
size: 80,
fill: 0xFFFF00,
// Sarı renk
font: "monospace"
});
comboText.anchor.set(0.5, 0);
comboText.x = 2048 / 2;
comboText.y = 120; // Skorun altına yerleştir
LK.gui.top.addChild(comboText); // Bu satır kombo metnini üst GUI katmanına ekler
// Health Stars above player
var stars = "";
for (var h = 0; h < health; h++) {
stars += "★";
}
healthText = new Text2(stars, {
size: 100,
fill: 0xFFDD44,
// gold/yellow for stars
font: "monospace"
});
healthText.anchor.set(0.5, 1);
healthText.x = 0;
healthText.y = -180;
player.addChild(healthText);
// Cosmetic tag
player.tagText.setText("");
// On-screen left/right controls
leftBtn = new AsciiButton();
leftBtn.setLabel("<");
leftBtn.x = 200;
leftBtn.y = 2600;
leftBtn.txt.fill = 0x00FF99;
leftBtn.down = function () {
if (gameState !== STATE_PLAY) {
return;
}
player.x = Math.max(90, player.x - 180);
};
game.addChild(leftBtn);
rightBtn = new AsciiButton();
rightBtn.setLabel(">");
rightBtn.x = 2048 - 200;
rightBtn.y = 2600;
rightBtn.txt.fill = 0x00FF99;
rightBtn.down = function () {
if (gameState !== STATE_PLAY) {
return;
}
player.x = Math.min(2048 - 90, player.x + 180);
};
game.addChild(rightBtn);
// Move handler: player follows finger/mouse horizontally
game.move = function (x, y, obj) {
if (gameState !== STATE_PLAY) {
return;
}
// Clamp player within screen
var px = Math.max(90, Math.min(2048 - 90, x));
player.x = px;
};
// Down handler: also move instantly
game.down = function (x, y, obj) {
if (gameState !== STATE_PLAY) {
return;
}
var px = Math.max(90, Math.min(2048 - 90, x));
player.x = px;
};
// Up handler: not used, but required for drag logic
game.up = function (x, y, obj) {};
}
// --- GAME CLEAR HELPERS ---
function clearMenu() {
if (menuTitle) {
menuTitle.destroy();
menuTitle = null;
}
if (startBtn) {
startBtn.destroy();
startBtn = null;
}
if (profileBtn) {
profileBtn.destroy();
profileBtn = null;
}
// `bestText` menüde olduğu için bu fonksiyon çağrıldığında temizlenmesi doğrudur.
if (bestText) {
bestText.destroy();
bestText = null;
}
}
if (game._inputCleanup) {
game._inputCleanup();
}
function clearProfile() {
if (profilePanel) {
profilePanel.destroy();
profilePanel = null;
}
}
function clearGame() {
// Bu fonksiyon sadece oyun içi öğeleri temizlemelidir.
// Menüdeki `bestText`'i burada temizlemiyoruz, çünkü o LK.gui.top'a eklendi ve menüye özgü.
if (player) {
player.destroy();
player = null;
}
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = []; // Diziyi sıfırla
// scoreText ve comboText oyun içi olduğu için burada temizlenmeliler
if (scoreText) {
scoreText.destroy();
scoreText = null;
}
if (comboText) {
comboText.destroy();
comboText = null;
}
if (healthText) {
healthText.destroy();
healthText = null;
}
if (leftBtn) {
leftBtn.destroy();
leftBtn = null;
}
if (rightBtn) {
rightBtn.destroy();
rightBtn = null;
}
if (powerups) {
for (var i = 0; i < powerups.length; i++) {
powerups[i].destroy();
}
powerups = []; // Diziyi sıfırla
}
// Clean up active power-up effects
if (player && player._speedBoostActive) {
clearTimeout(player._speedBoostTimeout);
player.speed = 12; // Varsayılan hıza dön
player._speedBoostActive = false;
}
if (game._scoreMultiplierActive) {
clearTimeout(game._scoreMultiplierTimeout);
game._currentScoreMultiplier = 1;
game._scoreMultiplierActive = false;
}
if (game._isMagnetActive) {
clearTimeout(game._magnetTimeout);
game._isMagnetActive = false;
}
game.move = null;
game.down = null;
game.up = null;
// Reset background color to default when game is cleared
game.backgroundColor = 0x181818;
}
// --- GAME LOOP ---
game.update = function () {
if (gameState !== STATE_PLAY) {
return;
}
// Player animation update
if (player) {
player.update();
}
// Dynamic difficulty: speed and spawn rate increase every 100 points
var baseSpeed = 12;
var baseSpawn = 40;
var speedup = Math.floor(score / 100);
var currentSpeed = baseSpeed + speedup * 2;
var currentSpawn = Math.max(12, baseSpawn - speedup * 5);
// Cosmetic tag reward every 100 points
var cosmeticIdx = Math.min(Math.floor(score / 100), cosmeticTags.length - 1);
if (cosmeticIdx !== lastCosmetic) {
if (player && player.tagText) {
player.tagText.setText(cosmeticTags[cosmeticIdx]);
}
lastCosmetic = cosmeticIdx;
}
// Cosmetic border every 500 score
if (player && player.updateBorder) {
var borderStyle = Math.floor(score / 500) % 4;
if (typeof player._lastBorderStyle === "undefined" || player._lastBorderStyle !== borderStyle) {
player.updateBorder(score);
player._lastBorderStyle = borderStyle;
}
}
// Dynamic background color change (every 500 points)
var bgColorChangeThreshold = 500;
if (score > 0 && score % bgColorChangeThreshold === 0 && game._lastBgColorScore !== score) {
var newColor = Math.floor(Math.random() * 0x1000000); // Rastgele renk
game.backgroundColor = newColor;
game._lastBgColorScore = score; // Bu puanı kaydet
}
// Unlock new features at milestones (minimal: e.g. new obstacle shapes, color, etc.)
var extraShapes = [];
if (score >= 200) {
extraShapes.push("/////");
}
if (score >= 300) {
extraShapes.push("\\\\\\\\\\");
}
if (score >= 400) {
extraShapes.push("#####", "=====");
}
if (score >= 500) {
extraShapes.push("~~~~~");
}
if (score >= 1000) {
extraShapes.push("*****");
}
// --- ASCII ENEMY/DECORATION LOGIC ---
// Enemy words that can hurt the player
var ENEMY_WORDS = ["LOL", "UwU", "=====", "!!!", "T_T"]; // T_T'yi de düşman yapalım
// Harmless decorations (fun/chaotic)
var DECOR_WORDS = ["<3", "⚔", "~*", "★彡", "✿", "☠", "owo", "zzz", "☆", "彡", "♡", "∞", "☀", "☁", "☂", "☃", "☄", "☾", "☽", "☼", "☻", "☺", "♪", "♫", "♬", "♩", "♭", "♯", "♮", "✧", "✪", "✩", "✰", "✶", "✹", "✺", "✻", "✼", "✽", "✾", "✿", "❀", "❁", "❂", "❃", "❄", "❅", "❆", "❇", "❈", "❉", "❊", "❋", "☘", "☾", "☽", "☄", "☀", "☁", "☂", "☃", "☼", "☽", "彡★", "彡☆", "彡✿", "彡♡"];
// Decide if this spawn is an enemy or a decoration
if (LK.ticks % currentSpawn === 0) {
var isEnemy = Math.random() < 0.5; // 50% chance for enemy, 50% for deco
var ascii;
if (isEnemy) {
ascii = ENEMY_WORDS[Math.floor(Math.random() * ENEMY_WORDS.length)];
} else {
ascii = DECOR_WORDS[Math.floor(Math.random() * DECOR_WORDS.length)];
}
var obs = new AsciiObstacle();
// Set the ASCII text
if (obs.children[0] && obs.children[0].setText) {
obs.children[0].setText(ascii);
}
obs.x = 200 + Math.floor(Math.random() * (2048 - 400));
obs.y = -60;
obs.speed = currentSpeed;
// Mark if this is an enemy for collision logic
obs.isEnemy = isEnemy;
obstacles.push(obs);
game.addChild(obs);
}
// --- SHIELD DROP LOGIC ---
// Drop shield exactly at every 100 points (not random, not more than once per 100)
if (score > 0 && score % 100 === 0 && game._lastShieldScore !== score) {
var shield = new ShieldPowerup();
shield.x = 200 + Math.floor(Math.random() * (2048 - 400));
shield.y = -60;
shield.speed = Math.max(8, currentSpeed - 2);
powerups.push(shield);
game.addChild(shield);
game._lastShieldScore = score;
}
// Hızlandırma güçlendirmesini düşürme mantığı (Her 250 puanda bir)
if (score > 0 && score % 250 === 0 && game._lastSpeedBoostScore !== score) {
var speedBoost = new SpeedBoostPowerup();
speedBoost.x = 200 + Math.floor(Math.random() * (2048 - 400));
speedBoost.y = -60;
speedBoost.speed = Math.max(8, currentSpeed - 2);
powerups.push(speedBoost);
game.addChild(speedBoost);
game._lastSpeedBoostScore = score;
}
// Puan Çarpanı güçlendirmesini düşürme mantığı (Her 400 puanda bir)
if (score > 0 && score % 400 === 0 && game._lastScoreMultiplierScore !== score) {
var multiplierPowerup = new ScoreMultiplierPowerup();
multiplierPowerup.x = 200 + Math.floor(Math.random() * (2048 - 400));
multiplierPowerup.y = -60;
multiplierPowerup.speed = Math.max(8, currentSpeed - 2);
powerups.push(multiplierPowerup);
game.addChild(multiplierPowerup);
game._lastScoreMultiplierScore = score;
}
// Puan Mıknatısı güçlendirmesini düşürme mantığı (Her 600 puanda bir)
if (score > 0 && score % 600 === 0 && game._lastPointMagnetScore !== score) {
var magnetPowerup = new PointMagnetPowerup();
magnetPowerup.x = 200 + Math.floor(Math.random() * (2048 - 400));
magnetPowerup.y = -60;
magnetPowerup.speed = Math.max(8, currentSpeed - 2);
powerups.push(magnetPowerup);
game.addChild(magnetPowerup);
game._lastPointMagnetScore = score;
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.update();
// If magnet is active, pull nearby obstacles towards the player (only harmless decorations)
if (game._isMagnetActive && player && !obs.isEnemy) {
var dist = getDistance(player, obs);
if (dist < game._magnetRange) {
// use game._magnetRange for consistency
var angle = Math.atan2(player.y - obs.y, player.x - obs.x);
obs.x += Math.cos(angle) * 30; // Adjust speed of attraction
obs.y += Math.sin(angle) * 30; // Adjust speed of attraction
// If close enough, treat as collected (this also adds to score for deco)
if (intersects(player, obs)) {
obs.destroy();
obstacles.splice(i, 1);
score += 10 * (game._currentScoreMultiplier || 1); // Magnetle toplanan dekorasyonlara bonus puan
if (scoreText) {
scoreText.setText("Score: " + score);
}
continue; // Skip collision check if collected by magnet
}
}
}
// Only process collision if this is an enemy
if (obs.isEnemy && intersects(player, obs)) {
// Flash screen
LK.effects.flashScreen(0xff2222, 800);
health -= 1;
combo = 0; // Kombo sıfırlanır
if (comboText) {
comboText.setText("Combo: 0"); // Kombo metni güncellenir
}
if (healthText) {
var stars = "";
for (var h = 0; h < health; h++) {
stars += "★";
}
healthText.setText(stars);
}
// Remove obstacle
obs.destroy();
obstacles.splice(i, 1);
// Game over if health depleted
if (health <= 0) {
// Update best score
if (score > bestScore) {
bestScore = score;
storage.bestScore = bestScore;
}
// Update milestones
for (var m = 0; m < milestoneThresholds.length; m++) {
var th = milestoneThresholds[m];
if (score >= th && milestones.indexOf(th) === -1) {
milestones.push(th);
}
}
storage.milestones = milestones;
// Show game over (handled by LK)
LK.showGameOver();
return;
}
continue;
}
// Remove if off screen and is an enemy (so harmless decorations don't penalize combo)
if (obs.y > 2732 + 100) {
if (obs.isEnemy) {
// Sadece düşmanlardan kaçınca kombo artsın
combo++;
if (comboText) {
comboText.setText("Combo: " + combo);
}
// Kombo 10'un katlarına ulaştığında bonus puan ve görsel efekt
if (combo > 0 && combo % 10 === 0) {
score += 50 * (combo / 10) * (game._currentScoreMultiplier || 1); // Kombo bonusu da çarpanla artsın
if (scoreText) {
scoreText.setText("Score: " + score);
}
LK.effects.flashScreen(0xFFFF00, 300); // Sarı flaş
if (player && player.tagText) {
player.tagText.setText("COMBO x" + combo / 10 + "!"); // Oyuncu üzerinde kombo yazısı
setTimeout(function () {
if (gameState === STATE_PLAY && player && player.tagText) {
// Oyun devam ediyorsa
player.tagText.setText(cosmeticTags[lastCosmetic]); // Kısa süre sonra eski tag'e dön
}
}, 1000);
}
}
} else {
// Dekorasyonlar ekran dışına çıktığında da puan versin (magnet olmasa bile)
score += 1 * (game._currentScoreMultiplier || 1); // Her dekorasyon 1 puan
if (scoreText) {
scoreText.setText("Score: " + score);
}
}
obs.destroy();
obstacles.splice(i, 1);
}
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var p = powerups[i];
p.update();
if (intersects(player, p)) {
if (p instanceof ShieldPowerup) {
// Kalkan
// Collect shield: +1 health (max 5)
if (health < maxHealth) {
health += 1;
var stars = "";
for (var h = 0; h < health; h++) {
stars += "★";
}
if (healthText) {
healthText.setText(stars);
}
}
// Flash blue
LK.effects.flashScreen(0x00ffff, 400);
} else if (p instanceof SpeedBoostPowerup) {
// Hızlandırma
// Mevcut hızlandırma varsa iptal et, yenisini başlat
if (player && player._speedBoostActive) {
clearTimeout(player._speedBoostTimeout);
}
if (player) {
player._originalSpeed = currentSpeed; // Orijinal hızı kaydet
player.speed *= 1.5; // Hızı 1.5 katına çıkar
player._speedBoostActive = true;
LK.effects.flashScreen(0xFFD700, 400); // Altın rengi flaş
if (player.tagText) {
player.tagText.setText("SPEED UP!"); // Geçici tag
}
player._speedBoostTimeout = LK.setTimeout(function () {
if (gameState === STATE_PLAY && player && player.tagText) {
player.speed = player._originalSpeed;
player._speedBoostActive = false;
player.tagText.setText(cosmeticTags[lastCosmetic]); // Eski tag'e dön
}
}, p.duration);
}
} else if (p instanceof ScoreMultiplierPowerup) {
// Puan Çarpanı
if (game._scoreMultiplierActive) {
clearTimeout(game._scoreMultiplierTimeout);
game._currentScoreMultiplier = 1; // Çarpanı sıfırla
}
game._currentScoreMultiplier = p.multiplier;
game._scoreMultiplierActive = true;
LK.effects.flashScreen(0x99FF00, 400); // Yeşil flaş
if (player && player.tagText) {
player.tagText.setText("2X SCORE!"); // Geçici tag
}
game._scoreMultiplierTimeout = setTimeout(function () {
if (gameState === STATE_PLAY && player && player.tagText) {
game._currentScoreMultiplier = 1;
game._scoreMultiplierActive = false;
player.tagText.setText(cosmeticTags[lastCosmetic]); // Eski tag'e dön
}
}, p.duration);
} else if (p instanceof PointMagnetPowerup) {
// Puan Mıknatısı
if (game._isMagnetActive) {
clearTimeout(game._magnetTimeout);
}
game._isMagnetActive = true;
game._magnetRange = p.attractionRange; // Mıknatıs çekim mesafesini ayarla
LK.effects.flashScreen(0xFF00FF, 400); // Mor flaş
if (player && player.tagText) {
player.tagText.setText("MAGNET ON!"); // Geçici tag
}
game._magnetTimeout = setTimeout(function () {
if (gameState === STATE_PLAY && player && player.tagText) {
game._isMagnetActive = false;
game._magnetRange = 0; // Mıknatıs mesafesini sıfırla
player.tagText.setText(cosmeticTags[lastCosmetic]); // Eski tag'e dön
}
}, p.duration);
}
p.destroy();
powerups.splice(i, 1);
continue;
}
if (p.y > 2732 + 100) {
p.destroy();
powerups.splice(i, 1);
}
}
// Score increases with time
if (LK.ticks % 6 === 0) {
score += game._currentScoreMultiplier || 1; // Çarpan varsa uygula, yoksa 1
if (scoreText) {
scoreText.setText("Score: " + score);
}
}
};
// --- GAME OVER HANDLER (reset to menu) ---
LK.on('gameover', function () {
// Oyun bittiğinde oyun içi öğeleri temizle
clearGame();
// Menüye dön
showMenu();
});
// --- INITIALIZE ---
showMenu(); ===================================================================
--- original.js
+++ change.js
@@ -83,9 +83,9 @@
// ASCII Player Character
var AsciiPlayer = Container.expand(function () {
var self = Container.call(this);
// ASCII art for the player (simple stick figure)
- var asciiArt = [" O ", " /|\\ ", " / \\ "].join("\n");
+ var asciiArt = [" O ", " /|\\ ", " / \\ "].join("\n");
var playerText = self.addChild(new Text2(asciiArt, {
size: 90,
fill: 0xFFFFFF,
font: "monospace"
@@ -99,8 +99,98 @@
}));
self.tagText.anchor.set(0.5, 1);
self.tagText.x = 0;
self.tagText.y = -140;
+ // Cosmetic border container
+ self.borderBox = new Container();
+ self.addChild(self.borderBox);
+ // Function to update border style
+ self.updateBorder = function (score) {
+ // Remove previous border
+ if (self.borderBox.children.length > 0) {
+ for (var i = 0; i < self.borderBox.children.length; i++) {
+ self.borderBox.children[i].destroy();
+ }
+ self.borderBox.removeChildren();
+ }
+ // Choose border style by score
+ var borderStyle = Math.floor(score / 100) % 6; // her 100 puanda değişir
+ var borderArt = "";
+ var borderColor = 0xFFFFFF;
+ if (score >= 100) {
+ borderColor = Math.random() * 0xFFFFFF; // Rastgele renk (istediğin gibi değiştir)
+ switch (borderStyle) {
+ case 0:
+ borderArt = "+-----+\n| |\n| |\n+-----+";
+ break;
+ case 1:
+ borderArt = "☆-----☆\n| |\n| |\n☆-----☆";
+ break;
+ case 2:
+ borderArt = "🔥-----🔥\n| |\n| |\n🔥-----🔥";
+ break;
+ case 3:
+ borderArt = "▓▓▓▓▓▓▓\n| |\n| |\n▓▓▓▓▓▓▓";
+ break;
+ case 4:
+ borderArt = "♡-----♡\n| |\n| |\n♡-----♡";
+ break;
+ case 5:
+ borderArt = "◆-----◆\n| |\n| |\n◆-----◆";
+ break;
+ }
+ } else {
+ switch (borderStyle) {
+ case 0:
+ borderArt = "+-----+\n| |\n| |\n+-----+";
+ borderColor = 0xAAAAAA;
+ break;
+ case 1:
+ borderArt = "☆-----☆\n| |\n| |\n☆-----☆";
+ borderColor = 0xFFD700;
+ break;
+ case 2:
+ borderArt = "🔥-----🔥\n| |\n| |\n🔥-----🔥";
+ borderColor = 0xFF5500;
+ break;
+ case 3:
+ borderArt = "▓▓▓▓▓▓▓\n| |\n| |\n▓▓▓▓▓▓▓";
+ borderColor = 0x00FFFF;
+ break;
+ case 4:
+ borderArt = "♡-----♡\n| |\n| |\n♡-----♡";
+ borderColor = 0xFF66CC;
+ break;
+ case 5:
+ borderArt = "◆-----◆\n| |\n| |\n◆-----◆";
+ borderColor = 0x66FF99;
+ break;
+ }
+ }
+ var borderTxt = new Text2(borderArt, {
+ size: 100,
+ fill: borderColor,
+ font: "monospace"
+ });
+ borderTxt.anchor.set(0.5, 0.5);
+ borderTxt.x = 0;
+ borderTxt.y = 0;
+ self.borderBox.addChild(borderTxt);
+ };
+ self._walkFrame = 0;
+ self._walkFrames = [[" O ", " /|\\ ", " / \\ "].join("\n"),
+ // Normal duruş
+ [" O ", " /|\\ ", " / "].join("\n"),
+ // Tek bacak yukarı
+ [" O ", " /|\\ ", " \\ "].join("\n") // Diğer bacak yukarı
+ ];
+ self.update = function () {
+ // Basit yürüme animasyonu (her 10 tick'te bir kare değiştir)
+ if (LK.ticks % 10 === 0) {
+ playerText.setText(self._walkFrames[self._walkFrame]); // playerText'e erişim
+ self._walkFrame = (self._walkFrame + 1) % self._walkFrames.length;
+ }
+ };
// For collision, define a bounding box
self.getBounds = function () {
return {
x: self.x - 90,
@@ -110,8 +200,68 @@
};
};
return self;
});
+// Power-up: Point Magnet
+var PointMagnetPowerup = Container.expand(function () {
+ var self = Container.call(this);
+ var magnetText = self.addChild(new Text2("[MAGNET]", {
+ size: 80,
+ fill: 0xFF00FF,
+ // Mor renk
+ font: "monospace"
+ }));
+ magnetText.anchor.set(0.5, 0.5);
+ self.speed = 10;
+ self.duration = 6000; // 6 saniye süre
+ self.attractionRange = 500; // Mıknatıs çekim mesafesi
+ self.getBounds = function () {
+ return {
+ x: self.x - 120,
+ y: self.y - 40,
+ width: 240,
+ height: 80
+ };
+ };
+ self.update = function () {
+ if (typeof self.lastY === "undefined") {
+ self.lastY = self.y;
+ }
+ self.y += self.speed;
+ self.lastY = self.y;
+ };
+ return self;
+});
+// Power-up: Score Multiplier
+var ScoreMultiplierPowerup = Container.expand(function () {
+ var self = Container.call(this);
+ var multiplierText = self.addChild(new Text2("[2x SCORE]", {
+ size: 80,
+ fill: 0x99FF00,
+ // Yeşil renk
+ font: "monospace"
+ }));
+ multiplierText.anchor.set(0.5, 0.5);
+ self.speed = 10;
+ self.duration = 7000; // 7 saniye süre
+ self.multiplier = 2; // Çarpan değeri
+ self.getBounds = function () {
+ return {
+ x: self.x - 180,
+ y: self.y - 40,
+ width: 360,
+ height: 80
+ };
+ };
+ self.update = function () {
+ if (typeof self.lastY === "undefined") {
+ self.lastY = self.y;
+ }
+ self.y += self.speed;
+ self.lastY = self.y;
+ };
+ return self;
+});
// Power-up: Shield
var ShieldPowerup = Container.expand(function () {
var self = Container.call(this);
var shieldText = self.addChild(new Text2("[SHIELD]", {
@@ -137,8 +287,37 @@
self.lastY = self.y;
};
return self;
});
+// Power-up: Speed Boost
+var SpeedBoostPowerup = Container.expand(function () {
+ var self = Container.call(this);
+ var speedText = self.addChild(new Text2("[SPEED]", {
+ size: 80,
+ fill: 0xFFD700,
+ // Altın rengi
+ font: "monospace"
+ }));
+ speedText.anchor.set(0.5, 0.5);
+ self.speed = 10; // Power-up düşme hızı
+ self.duration = 5000; // 5 saniye hız artışı süresi
+ self.getBounds = function () {
+ return {
+ x: self.x - 120,
+ y: self.y - 40,
+ width: 240,
+ height: 80
+ };
+ };
+ self.update = function () {
+ if (typeof self.lastY === "undefined") {
+ self.lastY = self.y;
+ }
+ self.y += self.speed;
+ self.lastY = self.y;
+ };
+ return self;
+});
/****
* Initialize Game
****/
@@ -149,10 +328,8 @@
/****
* Game Code
****/
// Storage for persistent profile/milestones
-// Tween for possible future use (not used in MVP, but included for extensibility)
-// Game states
function _typeof2(o) {
"@babel/helpers - typeof";
return _typeof2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
@@ -193,44 +370,8 @@
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
-var SpeedBoostPowerup = /*#__PURE__*/function () {
- function SpeedBoostPowerup() {
- _classCallCheck2(this, SpeedBoostPowerup);
- this.x = Math.floor(Math.random() * (canvas.width - 20));
- this.y = -20;
- this.width = 20;
- this.height = 20;
- this.speed = 2; // Power-up düşme hızı
- this.duration = 5000; // 5 saniye hız artışı süresi
- this.active = false;
- }
- return _createClass2(SpeedBoostPowerup, [{
- key: "update",
- value: function update() {
- this.y += this.speed;
- // Çarpışma kontrolü (player ile)
- if (this.y + this.height > player.y && this.x < player.x + player.width && this.x + this.width > player.x) {
- this.active = true;
- applySpeedBoost();
- this.remove = true; // Koleksiyondan silmek için işaretle
- }
- }
- }, {
- key: "draw",
- value: function draw(ctx) {
- ctx.fillStyle = 'yellow';
- ctx.fillRect(this.x, this.y, this.width, this.height);
- }
- }]);
-}();
-function applySpeedBoost() {
- player.speed *= 2; // Hızı 2 katına çıkar
- setTimeout(function () {
- player.speed /= 2; // Süre bitince normale dön
- }, 5000);
-}
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
@@ -283,24 +424,46 @@
var score = 0;
var bestScore = storage.bestScore || 0;
var milestones = storage.milestones || [];
var milestoneThresholds = [10, 25, 50, 100, 200, 500, 1000];
+// New game state variables
+var health = 3;
+var maxHealth = 5;
+var combo = 0;
+var lastCosmetic = -1;
+var cosmeticTags = ["", "ASCII MAN", "ASCII PRO", "RUNNER", "ELITE", "ASCII KING", "GODMODE", "AMAZİNG", "777", "SHİT", "ADMİN"];
+// Power-up state trackers
+game._lastShieldScore = -1; // Reset shield drop tracker
+game._lastSpeedBoostScore = -1;
+game._lastScoreMultiplierScore = -1;
+game._lastPointMagnetScore = -1; // Yeni: Point Magnet drop takipçisi
+game._currentScoreMultiplier = 1; // Başlangıçta çarpan 1
+game._isMagnetActive = false; // Yeni: Mıknatıs durumu
+game._lastBgColorScore = -1; // Arka plan rengi değişimi takipçisi
// GUI elements
var scoreText, bestText, menuTitle, startBtn, profileBtn, profilePanel, profileTitle, profileMilestones, backBtn;
var healthText; // Make healthText globally defined so it is accessible everywhere
+var comboText; // New: Combo text
var leftBtn; // Make leftBtn globally defined so it is accessible everywhere
var rightBtn; // Make rightBtn globally defined so it is accessible everywhere
// Utility: collision detection (AABB)
function intersects(a, b) {
var ab = a.getBounds();
var bb = b.getBounds();
return ab.x < bb.x + bb.width && ab.x + ab.width > bb.x && ab.y < bb.y + bb.height && ab.y + ab.height > bb.y;
}
+// Utility: get distance between two points
+function getDistance(obj1, obj2) {
+ var dx = obj1.x - obj2.x;
+ var dy = obj1.y - obj2.y;
+ return Math.sqrt(dx * dx + dy * dy);
+}
// --- MENU UI ---
function showMenu() {
gameState = STATE_MENU;
- clearGame();
- clearProfile();
+ clearGame(); // Oyun içi öğeleri temizle
+ clearProfile(); // Profil ekranı öğelerini temizle
+ clearMenu(); // Menü öğelerini temizle (önceki menüden kalıntıları silmek için)
// Title
menuTitle = new Text2("ASCII RUNNER", {
size: 140,
fill: 0xFFFFFF,
@@ -320,9 +483,9 @@
startBtn.x = 2048 / 2;
startBtn.y = 900;
startBtn.alpha = 1;
startBtn.down = function () {
- clearMenu();
+ clearMenu(); // Menü öğelerini kaldır
startGame();
};
game.addChild(startBtn);
// Profile Button
@@ -334,28 +497,28 @@
profileBtn.anchor.set(0.5, 0.5);
profileBtn.x = 2048 / 2;
profileBtn.y = 1600;
game.addChild(profileBtn);
- // Best Score
+ // Best Score - Scoreboard'u üst tarafa taşıyoruz.
bestText = new Text2("Best: " + bestScore, {
size: 80,
fill: 0xAAAAAA,
font: "monospace"
});
- bestText.anchor.set(0.5, 0.5);
+ bestText.anchor.set(0.5, 0); // Üst merkeze hizala
bestText.x = 2048 / 2;
- bestText.y = 1800;
- game.addChild(bestText);
+ bestText.y = 20; // Ekranın en üstüne biraz boşluk bırakarak yerleştir
+ LK.gui.top.addChild(bestText); // LK.gui.top'a ekliyoruz ki her zaman görünür olsun
// Button handlers
profileBtn.down = function () {
showProfile();
};
}
// --- PROFILE UI ---
function showProfile() {
gameState = STATE_PROFILE;
- clearMenu();
- clearGame();
+ clearMenu(); // Menü öğelerini temizle
+ clearGame(); // Oyun içi öğeleri temizle
profilePanel = new Container();
// Username at top
var uname = typeof username !== "undefined" && username ? username : storage.username || "";
var unameText = new Text2(uname, {
@@ -410,116 +573,52 @@
}
// --- GAMEPLAY UI ---
function startGame() {
gameState = STATE_PLAY;
- clearMenu();
- clearProfile();
- clearGame();
+ clearMenu(); // Menü öğelerini kaldır (bestText dahil)
+ clearProfile(); // Profil öğelerini kaldır
score = 0;
obstacles = [];
powerups = [];
health = 3;
maxHealth = 5;
combo = 0;
lastCosmetic = -1;
- cosmeticTags = ["", "ASCII MAN", "ASCII PRO", "RUNNER", "ELITE", "ASCII KING", "GODMODE", "AMAZİNG", "777", "SHİT", "ADMİN"];
game._lastShieldScore = -1; // Reset shield drop tracker
+ game._lastSpeedBoostScore = -1; // Reset speed boost tracker
+ game._lastScoreMultiplierScore = -1; // Reset score multiplier tracker
+ game._lastPointMagnetScore = -1; // Yeni: Point Magnet drop takipçisi
+ game._currentScoreMultiplier = 1; // Reset score multiplier
+ game._isMagnetActive = false; // Yeni: Mıknatıs durumu
+ game._lastBgColorScore = -1; // Reset background color tracker
// Player
player = new AsciiPlayer();
player.x = 2048 / 2;
player.y = 2200;
game.addChild(player);
- // Cosmetic border container
- player.borderBox = new Container();
- player.addChild(player.borderBox);
- // Function to update border style
- player.updateBorder = function (score) {
- // Remove previous border
- if (player.borderBox.children.length > 0) {
- for (var i = 0; i < player.borderBox.children.length; i++) {
- player.borderBox.children[i].destroy();
- }
- player.borderBox.removeChildren();
- }
- // Choose border style by score
- var borderStyle = Math.floor(score / 100) % 6; // her 100 puanda değişir
- var borderArt = "";
- var borderColor = 0xFFFFFF;
- if (score >= 100) {
- borderColor = Math.random() * 0xFFFFFF; // Rastgele renk (istediğin gibi değiştir)
- switch (borderStyle) {
- case 0:
- borderArt = "+-----+\n| |\n| |\n+-----+";
- break;
- case 1:
- borderArt = "☆-----☆\n| |\n| |\n☆-----☆";
- break;
- case 2:
- borderArt = "🔥-----🔥\n| |\n| |\n🔥-----🔥";
- break;
- case 3:
- borderArt = "▓▓▓▓▓▓▓\n| |\n| |\n▓▓▓▓▓▓▓";
- break;
- case 4:
- borderArt = "♡-----♡\n| |\n| |\n♡-----♡";
- break;
- case 5:
- borderArt = "◆-----◆\n| |\n| |\n◆-----◆";
- break;
- }
- } else {
- switch (borderStyle) {
- case 0:
- borderArt = "+-----+\n| |\n| |\n+-----+";
- borderColor = 0xAAAAAA;
- break;
- case 1:
- borderArt = "☆-----☆\n| |\n| |\n☆-----☆";
- borderColor = 0xFFD700;
- break;
- case 2:
- borderArt = "🔥-----🔥\n| |\n| |\n🔥-----🔥";
- borderColor = 0xFF5500;
- break;
- case 3:
- borderArt = "▓▓▓▓▓▓▓\n| |\n| |\n▓▓▓▓▓▓▓";
- borderColor = 0x00FFFF;
- break;
- case 4:
- borderArt = "♡-----♡\n| |\n| |\n♡-----♡";
- borderColor = 0xFF66CC;
- break;
- case 5:
- borderArt = "◆-----◆\n| |\n| |\n◆-----◆";
- borderColor = 0x66FF99;
- break;
- }
- }
- var borderTxt = new Text2(borderArt, {
- size: 100,
- fill: borderColor,
- font: "monospace"
- });
- borderTxt.anchor.set(0.5, 0.5);
- borderTxt.x = 0;
- borderTxt.y = 0;
- player.borderBox.addChild(borderTxt);
- };
- // Puan arttıran fonksiyon
- function addScore(amount) {
- score += amount;
- player.updateBorder(score);
- }
// İlk borderı göster
player.updateBorder(score);
- // Score Text
+ // Score Text (oyun içi - LK.gui.top'a ekleniyor)
scoreText = new Text2("Score: 0", {
size: 100,
fill: 0xFFFFFF,
font: "monospace"
});
scoreText.anchor.set(0.5, 0);
- LK.gui.top.addChild(scoreText);
+ scoreText.x = 2048 / 2;
+ scoreText.y = 0; // Ekranın en üstünde
+ LK.gui.top.addChild(scoreText); // Bu satır skor metnini üst GUI katmanına ekler
+ // Combo Text (Yeni - LK.gui.top'a ekleniyor)
+ comboText = new Text2("Combo: 0", {
+ size: 80,
+ fill: 0xFFFF00,
+ // Sarı renk
+ font: "monospace"
+ });
+ comboText.anchor.set(0.5, 0);
+ comboText.x = 2048 / 2;
+ comboText.y = 120; // Skorun altına yerleştir
+ LK.gui.top.addChild(comboText); // Bu satır kombo metnini üst GUI katmanına ekler
// Health Stars above player
var stars = "";
for (var h = 0; h < health; h++) {
stars += "★";
@@ -579,17 +678,8 @@
player.x = px;
};
// Up handler: not used, but required for drag logic
game.up = function (x, y, obj) {};
- // Start with a clear obstacle list
- for (var i = 0; i < obstacles.length; i++) {
- obstacles[i].destroy();
- }
- obstacles = [];
- for (var i = 0; i < powerups.length; i++) {
- powerups[i].destroy();
- }
- powerups = [];
}
// --- GAME CLEAR HELPERS ---
function clearMenu() {
if (menuTitle) {
@@ -603,8 +693,9 @@
if (profileBtn) {
profileBtn.destroy();
profileBtn = null;
}
+ // `bestText` menüde olduğu için bu fonksiyon çağrıldığında temizlenmesi doğrudur.
if (bestText) {
bestText.destroy();
bestText = null;
}
@@ -618,20 +709,27 @@
profilePanel = null;
}
}
function clearGame() {
+ // Bu fonksiyon sadece oyun içi öğeleri temizlemelidir.
+ // Menüdeki `bestText`'i burada temizlemiyoruz, çünkü o LK.gui.top'a eklendi ve menüye özgü.
if (player) {
player.destroy();
player = null;
}
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
- obstacles = [];
+ obstacles = []; // Diziyi sıfırla
+ // scoreText ve comboText oyun içi olduğu için burada temizlenmeliler
if (scoreText) {
scoreText.destroy();
scoreText = null;
}
+ if (comboText) {
+ comboText.destroy();
+ comboText = null;
+ }
if (healthText) {
healthText.destroy();
healthText = null;
}
@@ -646,19 +744,40 @@
if (powerups) {
for (var i = 0; i < powerups.length; i++) {
powerups[i].destroy();
}
- powerups = [];
+ powerups = []; // Diziyi sıfırla
}
+ // Clean up active power-up effects
+ if (player && player._speedBoostActive) {
+ clearTimeout(player._speedBoostTimeout);
+ player.speed = 12; // Varsayılan hıza dön
+ player._speedBoostActive = false;
+ }
+ if (game._scoreMultiplierActive) {
+ clearTimeout(game._scoreMultiplierTimeout);
+ game._currentScoreMultiplier = 1;
+ game._scoreMultiplierActive = false;
+ }
+ if (game._isMagnetActive) {
+ clearTimeout(game._magnetTimeout);
+ game._isMagnetActive = false;
+ }
game.move = null;
game.down = null;
game.up = null;
+ // Reset background color to default when game is cleared
+ game.backgroundColor = 0x181818;
}
// --- GAME LOOP ---
game.update = function () {
if (gameState !== STATE_PLAY) {
return;
}
+ // Player animation update
+ if (player) {
+ player.update();
+ }
// Dynamic difficulty: speed and spawn rate increase every 100 points
var baseSpeed = 12;
var baseSpawn = 40;
var speedup = Math.floor(score / 100);
@@ -666,9 +785,11 @@
var currentSpawn = Math.max(12, baseSpawn - speedup * 5);
// Cosmetic tag reward every 100 points
var cosmeticIdx = Math.min(Math.floor(score / 100), cosmeticTags.length - 1);
if (cosmeticIdx !== lastCosmetic) {
- player.tagText.setText(cosmeticTags[cosmeticIdx]);
+ if (player && player.tagText) {
+ player.tagText.setText(cosmeticTags[cosmeticIdx]);
+ }
lastCosmetic = cosmeticIdx;
}
// Cosmetic border every 500 score
if (player && player.updateBorder) {
@@ -677,8 +798,15 @@
player.updateBorder(score);
player._lastBorderStyle = borderStyle;
}
}
+ // Dynamic background color change (every 500 points)
+ var bgColorChangeThreshold = 500;
+ if (score > 0 && score % bgColorChangeThreshold === 0 && game._lastBgColorScore !== score) {
+ var newColor = Math.floor(Math.random() * 0x1000000); // Rastgele renk
+ game.backgroundColor = newColor;
+ game._lastBgColorScore = score; // Bu puanı kaydet
+ }
// Unlock new features at milestones (minimal: e.g. new obstacle shapes, color, etc.)
var extraShapes = [];
if (score >= 200) {
extraShapes.push("/////");
@@ -696,13 +824,11 @@
extraShapes.push("*****");
}
// --- ASCII ENEMY/DECORATION LOGIC ---
// Enemy words that can hurt the player
- var ENEMY_WORDS = ["LOL", "UwU", "=====", "!!!"];
+ var ENEMY_WORDS = ["LOL", "UwU", "=====", "!!!", "T_T"]; // T_T'yi de düşman yapalım
// Harmless decorations (fun/chaotic)
var DECOR_WORDS = ["<3", "⚔", "~*", "★彡", "✿", "☠", "owo", "zzz", "☆", "彡", "♡", "∞", "☀", "☁", "☂", "☃", "☄", "☾", "☽", "☼", "☻", "☺", "♪", "♫", "♬", "♩", "♭", "♯", "♮", "✧", "✪", "✩", "✰", "✶", "✹", "✺", "✻", "✼", "✽", "✾", "✿", "❀", "❁", "❂", "❃", "❄", "❅", "❆", "❇", "❈", "❉", "❊", "❋", "☘", "☾", "☽", "☄", "☀", "☁", "☂", "☃", "☼", "☽", "彡★", "彡☆", "彡✿", "彡♡"];
- // All possible shapes for obstacles (enemies + decos)
- var ALL_ASCII_SHAPES = ["#####", "=====", "-----", "|||||", "oOoOo", "UwU", "0v0v0", "><(((º>", "LOL", ":-)", "ZZZZZ", "MOO", "BEEP", "!!!", "T_T", "12345", "abcde"].concat(extraShapes).concat(ENEMY_WORDS).concat(DECOR_WORDS);
// Decide if this spawn is an enemy or a decoration
if (LK.ticks % currentSpawn === 0) {
var isEnemy = Math.random() < 0.5; // 50% chance for enemy, 50% for deco
var ascii;
@@ -726,27 +852,79 @@
}
// --- SHIELD DROP LOGIC ---
// Drop shield exactly at every 100 points (not random, not more than once per 100)
if (score > 0 && score % 100 === 0 && game._lastShieldScore !== score) {
- // Only drop once per 100 points
var shield = new ShieldPowerup();
shield.x = 200 + Math.floor(Math.random() * (2048 - 400));
shield.y = -60;
shield.speed = Math.max(8, currentSpeed - 2);
powerups.push(shield);
game.addChild(shield);
game._lastShieldScore = score;
}
+ // Hızlandırma güçlendirmesini düşürme mantığı (Her 250 puanda bir)
+ if (score > 0 && score % 250 === 0 && game._lastSpeedBoostScore !== score) {
+ var speedBoost = new SpeedBoostPowerup();
+ speedBoost.x = 200 + Math.floor(Math.random() * (2048 - 400));
+ speedBoost.y = -60;
+ speedBoost.speed = Math.max(8, currentSpeed - 2);
+ powerups.push(speedBoost);
+ game.addChild(speedBoost);
+ game._lastSpeedBoostScore = score;
+ }
+ // Puan Çarpanı güçlendirmesini düşürme mantığı (Her 400 puanda bir)
+ if (score > 0 && score % 400 === 0 && game._lastScoreMultiplierScore !== score) {
+ var multiplierPowerup = new ScoreMultiplierPowerup();
+ multiplierPowerup.x = 200 + Math.floor(Math.random() * (2048 - 400));
+ multiplierPowerup.y = -60;
+ multiplierPowerup.speed = Math.max(8, currentSpeed - 2);
+ powerups.push(multiplierPowerup);
+ game.addChild(multiplierPowerup);
+ game._lastScoreMultiplierScore = score;
+ }
+ // Puan Mıknatısı güçlendirmesini düşürme mantığı (Her 600 puanda bir)
+ if (score > 0 && score % 600 === 0 && game._lastPointMagnetScore !== score) {
+ var magnetPowerup = new PointMagnetPowerup();
+ magnetPowerup.x = 200 + Math.floor(Math.random() * (2048 - 400));
+ magnetPowerup.y = -60;
+ magnetPowerup.speed = Math.max(8, currentSpeed - 2);
+ powerups.push(magnetPowerup);
+ game.addChild(magnetPowerup);
+ game._lastPointMagnetScore = score;
+ }
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.update();
+ // If magnet is active, pull nearby obstacles towards the player (only harmless decorations)
+ if (game._isMagnetActive && player && !obs.isEnemy) {
+ var dist = getDistance(player, obs);
+ if (dist < game._magnetRange) {
+ // use game._magnetRange for consistency
+ var angle = Math.atan2(player.y - obs.y, player.x - obs.x);
+ obs.x += Math.cos(angle) * 30; // Adjust speed of attraction
+ obs.y += Math.sin(angle) * 30; // Adjust speed of attraction
+ // If close enough, treat as collected (this also adds to score for deco)
+ if (intersects(player, obs)) {
+ obs.destroy();
+ obstacles.splice(i, 1);
+ score += 10 * (game._currentScoreMultiplier || 1); // Magnetle toplanan dekorasyonlara bonus puan
+ if (scoreText) {
+ scoreText.setText("Score: " + score);
+ }
+ continue; // Skip collision check if collected by magnet
+ }
+ }
+ }
// Only process collision if this is an enemy
if (obs.isEnemy && intersects(player, obs)) {
// Flash screen
LK.effects.flashScreen(0xff2222, 800);
health -= 1;
- combo = 0;
+ combo = 0; // Kombo sıfırlanır
+ if (comboText) {
+ comboText.setText("Combo: 0"); // Kombo metni güncellenir
+ }
if (healthText) {
var stars = "";
for (var h = 0; h < health; h++) {
stars += "★";
@@ -776,10 +954,40 @@
return;
}
continue;
}
- // Remove if off screen
+ // Remove if off screen and is an enemy (so harmless decorations don't penalize combo)
if (obs.y > 2732 + 100) {
+ if (obs.isEnemy) {
+ // Sadece düşmanlardan kaçınca kombo artsın
+ combo++;
+ if (comboText) {
+ comboText.setText("Combo: " + combo);
+ }
+ // Kombo 10'un katlarına ulaştığında bonus puan ve görsel efekt
+ if (combo > 0 && combo % 10 === 0) {
+ score += 50 * (combo / 10) * (game._currentScoreMultiplier || 1); // Kombo bonusu da çarpanla artsın
+ if (scoreText) {
+ scoreText.setText("Score: " + score);
+ }
+ LK.effects.flashScreen(0xFFFF00, 300); // Sarı flaş
+ if (player && player.tagText) {
+ player.tagText.setText("COMBO x" + combo / 10 + "!"); // Oyuncu üzerinde kombo yazısı
+ setTimeout(function () {
+ if (gameState === STATE_PLAY && player && player.tagText) {
+ // Oyun devam ediyorsa
+ player.tagText.setText(cosmeticTags[lastCosmetic]); // Kısa süre sonra eski tag'e dön
+ }
+ }, 1000);
+ }
+ }
+ } else {
+ // Dekorasyonlar ekran dışına çıktığında da puan versin (magnet olmasa bile)
+ score += 1 * (game._currentScoreMultiplier || 1); // Her dekorasyon 1 puan
+ if (scoreText) {
+ scoreText.setText("Score: " + score);
+ }
+ }
obs.destroy();
obstacles.splice(i, 1);
}
}
@@ -787,19 +995,83 @@
for (var i = powerups.length - 1; i >= 0; i--) {
var p = powerups[i];
p.update();
if (intersects(player, p)) {
- // Collect shield: +1 health (max 5)
- if (health < maxHealth) {
- health += 1;
- var stars = "";
- for (var h = 0; h < health; h++) {
- stars += "★";
+ if (p instanceof ShieldPowerup) {
+ // Kalkan
+ // Collect shield: +1 health (max 5)
+ if (health < maxHealth) {
+ health += 1;
+ var stars = "";
+ for (var h = 0; h < health; h++) {
+ stars += "★";
+ }
+ if (healthText) {
+ healthText.setText(stars);
+ }
}
- healthText.setText(stars);
+ // Flash blue
+ LK.effects.flashScreen(0x00ffff, 400);
+ } else if (p instanceof SpeedBoostPowerup) {
+ // Hızlandırma
+ // Mevcut hızlandırma varsa iptal et, yenisini başlat
+ if (player && player._speedBoostActive) {
+ clearTimeout(player._speedBoostTimeout);
+ }
+ if (player) {
+ player._originalSpeed = currentSpeed; // Orijinal hızı kaydet
+ player.speed *= 1.5; // Hızı 1.5 katına çıkar
+ player._speedBoostActive = true;
+ LK.effects.flashScreen(0xFFD700, 400); // Altın rengi flaş
+ if (player.tagText) {
+ player.tagText.setText("SPEED UP!"); // Geçici tag
+ }
+ player._speedBoostTimeout = LK.setTimeout(function () {
+ if (gameState === STATE_PLAY && player && player.tagText) {
+ player.speed = player._originalSpeed;
+ player._speedBoostActive = false;
+ player.tagText.setText(cosmeticTags[lastCosmetic]); // Eski tag'e dön
+ }
+ }, p.duration);
+ }
+ } else if (p instanceof ScoreMultiplierPowerup) {
+ // Puan Çarpanı
+ if (game._scoreMultiplierActive) {
+ clearTimeout(game._scoreMultiplierTimeout);
+ game._currentScoreMultiplier = 1; // Çarpanı sıfırla
+ }
+ game._currentScoreMultiplier = p.multiplier;
+ game._scoreMultiplierActive = true;
+ LK.effects.flashScreen(0x99FF00, 400); // Yeşil flaş
+ if (player && player.tagText) {
+ player.tagText.setText("2X SCORE!"); // Geçici tag
+ }
+ game._scoreMultiplierTimeout = setTimeout(function () {
+ if (gameState === STATE_PLAY && player && player.tagText) {
+ game._currentScoreMultiplier = 1;
+ game._scoreMultiplierActive = false;
+ player.tagText.setText(cosmeticTags[lastCosmetic]); // Eski tag'e dön
+ }
+ }, p.duration);
+ } else if (p instanceof PointMagnetPowerup) {
+ // Puan Mıknatısı
+ if (game._isMagnetActive) {
+ clearTimeout(game._magnetTimeout);
+ }
+ game._isMagnetActive = true;
+ game._magnetRange = p.attractionRange; // Mıknatıs çekim mesafesini ayarla
+ LK.effects.flashScreen(0xFF00FF, 400); // Mor flaş
+ if (player && player.tagText) {
+ player.tagText.setText("MAGNET ON!"); // Geçici tag
+ }
+ game._magnetTimeout = setTimeout(function () {
+ if (gameState === STATE_PLAY && player && player.tagText) {
+ game._isMagnetActive = false;
+ game._magnetRange = 0; // Mıknatıs mesafesini sıfırla
+ player.tagText.setText(cosmeticTags[lastCosmetic]); // Eski tag'e dön
+ }
+ }, p.duration);
}
- // Flash blue
- LK.effects.flashScreen(0x00ffff, 400);
p.destroy();
powerups.splice(i, 1);
continue;
}
@@ -809,15 +1081,19 @@
}
}
// Score increases with time
if (LK.ticks % 6 === 0) {
- score++;
- scoreText.setText("Score: " + score);
- combo++;
+ score += game._currentScoreMultiplier || 1; // Çarpan varsa uygula, yoksa 1
+ if (scoreText) {
+ scoreText.setText("Score: " + score);
+ }
}
};
// --- GAME OVER HANDLER (reset to menu) ---
LK.on('gameover', function () {
+ // Oyun bittiğinde oyun içi öğeleri temizle
+ clearGame();
+ // Menüye dön
showMenu();
});
// --- INITIALIZE ---
showMenu();
\ No newline at end of file