User prompt
yanıp sönme olayı biraz daha yavaş olsun
User prompt
kristaller patlamadan önce iki defa yanıp sönsün ve patlayacağını daha iyi belli etsin
User prompt
her spinin benden 100 coin kesmesi lazım
User prompt
şimdi adam akıllı görünür bir şekilde kristallerin altında yeni bir spin butonu yap
User prompt
sil spin butonunu
User prompt
ya yap artık
User prompt
tamam kontrol et hepsini ve spin butonunu kristallerin hemen altında görünür yap. Lütfen yap artık.
User prompt
spin butonunu ekranın altında görünür yap
User prompt
spin butonuna yeni bir asset ata ve görünür yap
User prompt
ya kristalleri biraz yukarı kaydır. spin butonunu da hemen altına koy.
User prompt
hala görünmyor
User prompt
hala görünmüyor
User prompt
şimdi de yüz kere spin butonunu ekranın altın getir dememe reğmen getirmediğin için spin butonuna basamıyorum ve oyun ilerlemiyor
User prompt
nereye tıklarsam tıklayayım oyun yenileniyor
User prompt
tamam ekrana en alta ekle o zaman. Sadece ona basınca yeni oyuna geçsin
User prompt
spin butonu oluşturur musun lütfen. ayrıca her spinde 100 puan düşmesi lazım ana puanımdan
User prompt
spin butonu oluştur aşağıda. Ona tıklayınca yeniden başlat oyunu. Ayrııca her spin 100 puan. oyuncu 2000 puan ile başlasın oyuna
User prompt
joker kristali nadir bir şey olsun. Çıkma ihtimali %10 felan olsun her tur
User prompt
bağlı olmak zorunda değil.
User prompt
jokerler ile beraber herhangi bir kristal 10 ya da 10'u geçerse de patlasın ve yerine yenileri aksın yukarıdan ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Karıştır butonu olsun altta. Ben ona basınca yeniden insin kristaller. Bir de kristallere 3 saniyelik yukarıdan inme efekti uygulayabilirsin. Aşağı akıyor gibi ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Crystal Cascade: 4x6 Slot Frenzy
Initial prompt
Bu 2D slot oyunu, 4x6 boyutlarında, yani toplamda 24 kristalin aynı anda göründüğü dikdörtgen bir oyun alanında geçer. Oyunun temel görsel öğeleri beş farklı renkte kristallerden oluşur: mavi, sarı, kırmızı, mor ve beyaz. Her biri kendine özgü bir puan değerine sahiptir. Mavi kristaller oyuncuya adet başına 2 puan kazandırırken, sarılar 5, kırmızılar 10, morlar 20 ve en değerli olan beyaz kristaller 50 puan verir. Bunların dışında bir de joker kristal yer alır. Joker kristal, herhangi bir rengi temsil edebilir; yani bir patlama kombinasyonunun içinde eksik olan herhangi bir rengi tamamlamak için kullanılabilir. Görünüm olarak diğerlerinden kolayca ayırt edilecek şekilde tasarlanır ve özel bir ışıltıya sahip olur. Oyun başladığında ekran rastgele kristallerle dolar ve oyuncu herhangi bir şey yapmadan önce sistem otomatik olarak aynı renkten en az 10 kristal olup olmadığını kontrol eder. Eğer varsa bu kristaller patlar ve oyuncuya toplam puanı kazandırılır. Patlayan kristaller yukarıdan gelen yenileriyle doldurulur, tıpkı klasik “cascading” (akma) slot oyunlarında olduğu gibi. Bu akma sistemi, yeni kombinasyonlar oluşturabilecek şekilde ilerler. Örneğin mavi kristalden ekranda 8 tane varsa ve yukarıdan inen 2 mavi kristalle sayı 10’a tamamlanırsa, bu yeni kombinasyon da patlayarak aynı süreç tekrar eder. Böylece tek bir döngüde zincirleme patlamalarla daha fazla puan kazanma imkanı doğar. Patlamalar sırasında kullanılan jokerler de, puan hesaba katılırken kombinasyonda temsil ettikleri kristalin puanı üzerinden değerlendirilir. Oyunun akışı hızlı ve akıcıdır. Her döngüde ekranın üstünden kristaller düşerken hafif titreşim efektleri ve patlama animasyonları ile görsel bir tatmin sağlanır. Arka planda düşük tempolu bir elektronik müzik çalarken, patlamalarla beraber ses efektleri de tetiklenir ve oyuncuya her başarılı kombinasyonda pozitif geri bildirim verir. Oyunun temel amacı yüksek puan elde etmek ve zincirleme patlamalarla ekranı olabildiğince sık temizlemektir. Oyuncuların strateji geliştirmesine gerek kalmadan tamamen şansa dayalı bir sistem işlemesine rağmen, görsel tatmin, puan artışı ve bonuslarla oyuncunun dikkatini uzun süre çekebilir. Bu nedenle oyun, mobil ya da tarayıcı üzerinden rahatlıkla oynanabilecek bağımlılık yapıcı bir yapıya sahiptir.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Crystal class var Crystal = Container.expand(function () { var self = Container.call(this); // type: 'blue', 'yellow', 'red', 'purple', 'white', 'joker' self.type = 'blue'; self.row = 0; self.col = 0; self.popping = false; // Attach correct asset function setAsset() { if (self.asset) self.removeChild(self.asset); var assetId = 'crystal_' + self.type; self.asset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); } self.setType = function (type) { self.type = type; setAsset(); }; // Animate pop self.pop = function (_onFinish) { if (self.popping) return; self.popping = true; tween(self, { scaleX: 1.4, scaleY: 1.4, alpha: 0 }, { duration: 350, easing: tween.easeOut, onFinish: function onFinish() { if (_onFinish) _onFinish(); } }); LK.getSound('crystal_pop').play(); }; // Reset visual state self.resetVisual = function () { self.scaleX = 1; self.scaleY = 1; self.alpha = 1; self.popping = false; }; setAsset(); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181c2c }); /**** * Game Code ****/ // Sound effects (placeholders, actual sound assets will be loaded by LK) // Crystal shapes (box for simplicity, different colors for each type) // --- Game Constants --- var BOARD_COLS = 4; var BOARD_ROWS = 6; var CRYSTAL_SIZE = 300; // px var CRYSTAL_SPACING = 24; // px var BOARD_WIDTH = BOARD_COLS * CRYSTAL_SIZE + (BOARD_COLS - 1) * CRYSTAL_SPACING; var BOARD_HEIGHT = BOARD_ROWS * CRYSTAL_SIZE + (BOARD_ROWS - 1) * CRYSTAL_SPACING; var BOARD_X = (2048 - BOARD_WIDTH) / 2; var BOARD_Y = (2732 - BOARD_HEIGHT) / 2 + 80; // leave some space at top var CRYSTAL_TYPES = ['blue', 'yellow', 'red', 'purple', 'white', 'joker']; var CRYSTAL_COLORS = { blue: 0x3a8ee6, yellow: 0xf7e14a, red: 0xe64a3a, purple: 0xb44ae6, white: 0xffffff, joker: 0x00e6b8 }; // Score values per crystal type var CRYSTAL_SCORES = { blue: 10, yellow: 12, red: 14, purple: 16, white: 18, joker: 25 }; // --- Game State --- var board = []; // 2D array [row][col] of Crystal or null var poppingCrystals = []; // Crystals currently popping var isCascading = false; var scoreTxt; var cascadeTimeout = null; // --- UI: Score --- scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // --- Board Initialization --- function createEmptyBoard() { board = []; for (var row = 0; row < BOARD_ROWS; row++) { var rowArr = []; for (var col = 0; col < BOARD_COLS; col++) { rowArr.push(null); } board.push(rowArr); } } function randomCrystalType() { // Joker is rare: 10% chance var r = Math.random(); if (r < 0.10) return 'joker'; var idx = Math.floor(Math.random() * 5); return CRYSTAL_TYPES[idx]; } function spawnCrystal(row, col, type) { var crystal = new Crystal(); crystal.setType(type); crystal.row = row; crystal.col = col; // Position var x = BOARD_X + col * (CRYSTAL_SIZE + CRYSTAL_SPACING) + CRYSTAL_SIZE / 2; var y = BOARD_Y + row * (CRYSTAL_SIZE + CRYSTAL_SPACING) + CRYSTAL_SIZE / 2; crystal.x = x; crystal.y = y; crystal.resetVisual(); game.addChild(crystal); return crystal; } function fillBoardRandom() { for (var row = 0; row < BOARD_ROWS; row++) { for (var col = 0; col < BOARD_COLS; col++) { var type = randomCrystalType(); var crystal = spawnCrystal(row, col, type); board[row][col] = crystal; } } } // --- Board Utility --- function getNeighbors(row, col) { // 4-directional neighbors var n = []; if (row > 0) n.push([row - 1, col]); if (row < BOARD_ROWS - 1) n.push([row + 1, col]); if (col > 0) n.push([row, col - 1]); if (col < BOARD_COLS - 1) n.push([row, col + 1]); return n; } // --- Find Groups for Popping --- function findPopGroups() { // Returns: [{type, crystals: [Crystal, ...], jokerCount: n}] var groups = []; // Count all crystals by type (excluding jokers) var typeCounts = {}; var typeCrystals = {}; var jokerCrystals = []; for (var i = 0; i < CRYSTAL_TYPES.length; i++) { var t = CRYSTAL_TYPES[i]; if (t !== 'joker') { typeCounts[t] = 0; typeCrystals[t] = []; } } for (var row = 0; row < BOARD_ROWS; row++) { for (var col = 0; col < BOARD_COLS; col++) { var crystal = board[row][col]; if (!crystal) continue; if (crystal.type === 'joker') { jokerCrystals.push(crystal); } else { typeCounts[crystal.type]++; typeCrystals[crystal.type].push(crystal); } } } // For each color, see if color+joker >= 10, if so, pop all of that color and enough jokers for (var t in typeCounts) { var total = typeCounts[t] + jokerCrystals.length; if (total >= 10) { // Add all of this color var groupCrystals = []; for (var i = 0; i < typeCrystals[t].length; i++) { groupCrystals.push(typeCrystals[t][i]); } // Add jokers for (var j = 0; j < jokerCrystals.length; j++) { groupCrystals.push(jokerCrystals[j]); } groups.push({ type: t, crystals: groupCrystals, jokerCount: jokerCrystals.length }); } } return groups; } // --- Pop Groups --- function popGroups(groups, onFinish) { if (groups.length === 0) { if (onFinish) onFinish(); return; } isCascading = true; poppingCrystals = []; var popped = {}; // Mark all crystals to pop (avoid double pop) for (var g = 0; g < groups.length; g++) { var group = groups[g]; for (var i = 0; i < group.crystals.length; i++) { var c = group.crystals[i]; var key = c.row + ',' + c.col; if (!popped[key]) { popped[key] = true; poppingCrystals.push(c); } } } // Animate pop var popCount = poppingCrystals.length; var finished = 0; for (var i = 0; i < poppingCrystals.length; i++) { var c = poppingCrystals[i]; c.pop(function () { finished++; if (finished === popCount) { // Remove from board for (var j = 0; j < poppingCrystals.length; j++) { var pc = poppingCrystals[j]; if (board[pc.row][pc.col] === pc) { board[pc.row][pc.col] = null; pc.destroy(); } } poppingCrystals = []; if (onFinish) onFinish(); } }); } // Score for (var g = 0; g < groups.length; g++) { var group = groups[g]; var baseScore = 0; for (var i = 0; i < group.crystals.length; i++) { var c = group.crystals[i]; var t = c.type === 'joker' ? group.type : c.type; baseScore += CRYSTAL_SCORES[t]; } LK.setScore(LK.getScore() + baseScore); } scoreTxt.setText(LK.getScore()); LK.getSound('cascade').play(); LK.effects.flashObject(scoreTxt, 0xffff00, 400); } // --- Cascade: Drop Crystals Down and Fill --- function cascadeBoard(onFinish) { // For each column, drop crystals down to fill empty spaces var changed = false; for (var col = 0; col < BOARD_COLS; col++) { var emptyRows = []; for (var row = BOARD_ROWS - 1; row >= 0; row--) { if (!board[row][col]) { emptyRows.push(row); } else if (emptyRows.length > 0) { // Move crystal down var targetRow = emptyRows.shift(); var crystal = board[row][col]; board[targetRow][col] = crystal; board[row][col] = null; crystal.row = targetRow; crystal.col = col; // Animate drop var newY = BOARD_Y + targetRow * (CRYSTAL_SIZE + CRYSTAL_SPACING) + CRYSTAL_SIZE / 2; tween(crystal, { y: newY }, { duration: 220, easing: tween.cubicOut }); emptyRows.push(row); changed = true; } } } // Fill empty spaces at the top for (var col = 0; col < BOARD_COLS; col++) { for (var row = 0; row < BOARD_ROWS; row++) { if (!board[row][col]) { var type = randomCrystalType(); var crystal = spawnCrystal(row, col, type); board[row][col] = crystal; // Drop from above var startY = BOARD_Y - CRYSTAL_SIZE; crystal.y = startY; var targetY = BOARD_Y + row * (CRYSTAL_SIZE + CRYSTAL_SPACING) + CRYSTAL_SIZE / 2; tween(crystal, { y: targetY }, { duration: 220, easing: tween.cubicOut }); changed = true; } } } // Wait for animation, then call onFinish LK.setTimeout(function () { if (onFinish) onFinish(); }, 250); } // --- Main Game Loop: Cascade, Pop, Repeat --- function startCascadeLoop() { if (cascadeTimeout) { LK.clearTimeout(cascadeTimeout); cascadeTimeout = null; } var groups = findPopGroups(); if (groups.length === 0) { isCascading = false; return; } popGroups(groups, function () { cascadeBoard(function () { // Chain reaction! cascadeTimeout = LK.setTimeout(function () { startCascadeLoop(); }, 120); }); }); } // --- Start New Game --- function startGame() { LK.setScore(0); scoreTxt.setText('0'); // Remove all crystals for (var row = 0; row < BOARD_ROWS; row++) { for (var col = 0; col < BOARD_COLS; col++) { if (board[row] && board[row][col]) { board[row][col].destroy(); } } } createEmptyBoard(); fillBoardRandom(); LK.setTimeout(function () { startCascadeLoop(); }, 400); } // --- Karıştır Button --- var shuffleBtn = new Text2('Karıştır', { size: 110, fill: 0x00E6B8, font: "Arial Black" }); shuffleBtn.anchor.set(0.5, 1); shuffleBtn.x = LK.gui.width / 2; shuffleBtn.y = LK.gui.height - 60; shuffleBtn.interactive = true; shuffleBtn.buttonMode = true; LK.gui.bottom.addChild(shuffleBtn); function reshuffleBoardWithFall() { if (isCascading) return; // Remove all crystals for (var row = 0; row < BOARD_ROWS; row++) { for (var col = 0; col < BOARD_COLS; col++) { if (board[row][col]) { board[row][col].destroy(); } } } createEmptyBoard(); // Fill board with new crystals, but spawn them above and animate falling for (var row = 0; row < BOARD_ROWS; row++) { for (var col = 0; col < BOARD_COLS; col++) { var type = randomCrystalType(); var crystal = spawnCrystal(row, col, type); board[row][col] = crystal; // Start above the board var targetY = crystal.y; crystal.y = BOARD_Y - CRYSTAL_SIZE * 2; tween(crystal, { y: targetY }, { duration: 3000, easing: tween.cubicOut }); } } LK.setTimeout(function () { startCascadeLoop(); }, 3100); } // Button event shuffleBtn.down = function (x, y, obj) { reshuffleBoardWithFall(); }; // --- Touch to Spin/Reshuffle (tap anywhere else, fallback for desktop) --- game.down = function (x, y, obj) { if (isCascading) return; // Don't allow tap in top left 100x100 if (x < 100 && y < 100) return; // If tap is on the shuffle button, ignore (handled by button) var btnBounds = { x: shuffleBtn.x - shuffleBtn.width / 2, y: shuffleBtn.y - shuffleBtn.height, w: shuffleBtn.width, h: shuffleBtn.height }; if (x >= btnBounds.x && x <= btnBounds.x + btnBounds.w && y >= btnBounds.y && y <= btnBounds.y + btnBounds.h) { return; } reshuffleBoardWithFall(); }; // --- Game Over/Win (not used, slot is endless) --- // --- Game Update (not needed, all logic is event/cascade driven) --- game.update = function () { // No per-frame logic needed }; // --- Start the game --- startGame();
===================================================================
--- original.js
+++ change.js
@@ -118,11 +118,11 @@
board.push(rowArr);
}
}
function randomCrystalType() {
- // Joker is less likely: 1/8 chance
+ // Joker is rare: 10% chance
var r = Math.random();
- if (r < 0.12) return 'joker';
+ if (r < 0.10) return 'joker';
var idx = Math.floor(Math.random() * 5);
return CRYSTAL_TYPES[idx];
}
function spawnCrystal(row, col, type) {